
/* ==========================================================================
   Stablex Hub — design system.
   One hand-written stylesheet. No Tailwind, no build step.

   WHY NO UTILITY FRAMEWORK: in v1, `base.css` loaded after Tailwind and was
   unlayered, so a shorthand in a `.sx-*` class silently beat any utility the
   caller applied. Classes looked applied and were dead. Owning the whole
   vocabulary removes that failure mode entirely.

   THE LOOK IS THE ORIGINAL MKK APP'S, BY THE OWNER'S CHOICE — values measured
   from STABLEX_UI_Template/styles.css and the MKK v1.3.0 release: graph-paper
   page (#f5f6f5 + 48px grid), white cards with a REAL 1px border and a
   whisper shadow, the red top bar on metric/board cards (warm #ddc9cb frame),
   red uppercase eyebrows, a 4px red left bar on the hero header, square
   corners, 42px bordered buttons, and a wine sidebar. Red text is for
   eyebrows, links and accents; VALUES are ink.

   WHAT MOVED SINCE, and it is the whole of it: the red is now the company's
   own #dc0005 rather than the muted #a31820 — vivid where colour is colour,
   a dark step where colour is text, because the vivid one does not clear
   4.5:1 on the page ground. The rail follows it into the same hue. And the
   graph paper carries a curve: three summed sines in an embedded SVG, on the
   page, in the hero panel and low in the rail. It does not move.
   ========================================================================== */

:root {
  /*
   * CONTRAST IS A MEASUREMENT, NOT A TASTE. Every value below was measured
   * against its own background and moved only as far as its floor required.
   * `bun run check` re-measures them on every run and fails if one slips.
   *
   * What was wrong, measured on the shipped palette:
   *   card vs page   1.08:1  - a white card on a #f5f6f5 page is invisible;
   *                            the whole screen read as one sheet of paper
   *   card border    1.27:1  - so the edge could not rescue it either
   *   input border   1.50:1  - WCAG 1.4.11 asks 3:1 for a control's own
   *                            boundary; a form field had no visible edge
   *   muted text     4.21:1  - under the 4.5:1 floor, and it is the colour
   *                            of every hint, card-note and table label
   *
   * The MKK language is untouched: cool greys, square corners, a REAL 1px
   * frame, red for eyebrows and accents only. The frame is simply a line you
   * can see now instead of one you had to infer.
   */

  /* -- surfaces: graph-paper page, white panels -- */
  --surface-page:       #e9edf0;
  --surface:            #ffffff;
  --surface-sunken:     #f0f4f7;
  /*
   * THE HEAD BAND AND THE GROUP BAND (2026-10-29). Grey bands - even
   * --surface-sunken - read as the PAGE showing through the pane ("arka
   * planla aynı"): between the page (#e9edf0) and white there is no grey
   * the eye tells apart. A cool blue tint differs from the page by hue.
   * Heads and feet of panes and cards take the light one; a list's group
   * names ("Hedefleri girin", "1. onayı ver") the stronger one.
   */
  --surface-band-head:  #e8eff8;
  --surface-band-group: #dbe6f2;

  /*
   * WHAT A PANEL STANDS ON — and it depends on where the panel is.
   *
   * A boş durum kutusu, a kanban column, a help panel: each is a block that
   * needs a ground of its own. Inside a card it should RECEDE from the card
   * (--surface-sunken). Directly on the page there is nothing to recede
   * from, and using the recessed tone there put the block at 1.065 against
   * the page - measured, and for practical purposes the same colour. On the
   * page the panel IS the ground, so it takes --surface.
   *
   * One variable rather than a pair of rules per class: adding a panel means
   * adding it to the list below, not remembering to write the override too.
   * And this deliberately does NOT cover chips, neutral badges or disabled
   * controls - those need a fill wherever they are, and turning them white
   * on the page would make a disabled box look enabled.
   */
  --panel-ground:       var(--surface);
  --surface-control:    #ffffff;
  --surface-hover:      #e9eef3;
  --surface-selected:   #fbf1f1;
  --surface-row-alt:    #f4f7f9;
  --surface-row-hover:  #e9eef3;
  --surface-head:       color-mix(in srgb, var(--text-body) 6%, var(--surface));
  /*
   * THE CARD'S NAME BAND. Warm on purpose, and the reason is arithmetic:
   * between the page (#e9edf0, luminance .842) and a white card (1.000) there
   * is almost no room left, so a GREY band would either vanish into the body
   * or merge with the page above it. A warm band differs from the cool page
   * by HUE, which the eye reads at equal lightness - and it is already the
   * app's own language: the MKK metric and board cards carry a warm frame.
   * Literal, not color-mix(), so `bun run check` can measure it.
   */
  --surface-band:       #fdeceb;

  /* -- text: the template's ink ramp -- */
  --text-body:      #182331;
  --text-secondary: #566475;
  --text-muted:     #606b7a;
  --text-icon:      #84909d;
  --text-on-accent: #ffffff;

  /* -- borders: cool hairlines, plus the WARM frame that carries a red top
        bar (metric tiles, board cards, home tiles - measured #ddc9cb) -- */
  /* The graph-paper rule. A token because the grid tile is an embedded SVG
     and the gate insists every colour written literally inside one has a
     token equal to it — see the pattern scan in scripts/check.ts. */
  --grid-line:         #182331;
  /*
   * THE PAPER ITSELF, AND THE ONE TOKEN light-dark() CANNOT HOLD.
   *
   * light-dark() takes colours, not images, so the two themes' tiles are two
   * declarations rather than two arguments. Hoisting the URI into a token is
   * still a net win: the content column and the login screen each carried
   * their own byte-identical copy, and a copy is a thing that drifts.
   *
   * The colour inside is written by hand because a data: URI is a separate
   * document and cannot read var() -- which is exactly why --grid-line above
   * exists and why the gate checks every pattern colour against the palette.
   */
  --paper-tile: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48'%3E%3Cpath d='M0 0.5H48M0.5 0V48' stroke='%23182331' stroke-opacity='0.09' stroke-width='1'/%3E%3C/svg%3E");
  --border:            #ccd5de;
  --border-subtle:     #dde4ea;
  --border-input:      #8b95a1;
  --border-hover:      #687484;
  --border-warm:       #dfbab5;
  /*
   * A BUTTON'S EDGE IS A CONTROL BOUNDARY TOO. These were hardcoded
   * (#cad3dc / #e5c4c6) and measured 1.51:1 and 1.56:1 against their own
   * fill - the same failure the input borders had, hidden from the gate
   * because a literal colour is not a token. White and outlined-danger
   * buttons are most of the buttons in this app.
   */
  --border-button:     #8b95a1;
  --border-danger:     #a38b8d;
  --surface-danger:    #fffafa;

  /*
   * -- accent: THE HOUSE RED, and it is two colours on purpose --
   *
   * The ramp is the company's own: `--brand: #dc0005` and its dark steps are
   * declared in the Stablex report editor's token file and used 1581 times
   * across the original applications, against 267 for the muted #a31820 this
   * palette used to carry. #dc0005 is the red people here mean.
   *
   * IT CANNOT BE THE TEXT COLOUR. Measured against the three grounds text is
   * read on, #dc0005 is 5.19:1 on white, 4.41:1 on the page and 4.60:1 on the
   * band — it fails WCAG 1.4.3 on the page, which is where every eyebrow, note
   * and section caption sits. The brand red published on the web (#e0362a) is
   * worse: 4.44 / 3.77 / 3.94, failing on all three.
   *
   * So the vivid tone does the work colour is actually for — bars, fills,
   * strips, the button people press — and TEXT takes the ramp's own dark step
   * `--brand-700` (#b00004, 6.26:1 at its worst). Both are the same red; only
   * the lightness differs, which is exactly what a ramp is for.
   *
   * White on the filled button measures 5.19:1. That pair is now IN the gate
   * (scripts/check.ts) rather than trusted, because a vivid fill is precisely
   * the one that can drift under the floor without anybody seeing it.
   */
  --accent:        #e0362a;
  --accent-solid:  #d12b20;
  --accent-hover:  #b91c1c;
  --accent-active: #97160f;
  --accent-text:   #b91c1c;
  --accent-tint:   #fce3e0;
  /*
   * The focus ring. It was the hover ring too, written twice as a literal
   * `rgba(163, 24, 32, .28)` — so when the accent moved the rings did not,
   * the drift a named colour exists to stop. Hover now draws a soft glow from
   * `--accent` directly (see `a.tile:hover`); what stays here is the ring a
   * KEYBOARD needs, where a crisp edge is the point and a glow would be
   * worse than useless.
   */
  --accent-ring:   rgba(224, 54, 42, .32);

  /*
   * -- department colours (home tile top bars and chips) --
   *
   * Muhasebe is the Excel green, because the department's own tool is an
   * Excel studio. Hukuk is visne curugu, the claret on a Turkish judge's
   * robe - the bar's own green was the other candidate and Muhasebe has
   * it. Every one of these is also TEXT on the tile's foot line, so all
   * of them are measured by the contrast scan against the card surface
   * in both palettes. --dept-general is the exception and it is written
   * down there, not here.
   */
  --dept-general:   #e0362a;
  --dept-finance:   #6d4aa8;
  --dept-treasury:  #0f6cbd;
  --dept-marketing: #a92a7f;
  --dept-accounting:#217346;
  --dept-legal:     #6e1b32;

  /* -- chart series: one colour per compared thing (charts.ts columnChart).
     The volume screens compare three exchanges; these are the original
     application's colours for them, blue / bordeaux / yellow. -- */
  --series-1: #2563eb;
  --series-2: #7e1820;
  --series-3: #d4a106;

  /* -- semantic (greens/oranges from the template) -- */
  /*
   * GREEN IS TWO COLOURS FOR THE REASON RED IS TWO COLOURS.
   *
   * White on --ok measures 3.81:1 - under the 4.5 floor - and it was
   * painted that way on the finished board card. The gate could not see
   * it because the white was a literal in a rule, not a token, so the
   * pair was never in the list. --ok stays where colour is colour
   * (borders, legends, dots); --ok-solid (5.35:1) is for anything
   * carrying white text. Exactly the --accent / --accent-solid split.
   */
  --ok:        #159565;  --ok-tint:      #e4f6ef;  --ok-text:      #116e4a;
  --ok-solid:  #0f7a52;
  --warn:      #aa6612;  --warn-tint:    #fff4df;  --warn-text:    #8a530e;
  --error:     #9d1d25;  --error-tint:   #fdf3f3;  --error-text:   #841219;
  --info:      #0f6cbd;  --info-tint:    #ecf3fa;  --info-text:    #0b4e88;

  /* -- geometry: SOFT. Controls 6px, small marks 4px, panels 10px; only
        avatars, icon discs, dots and counts are round (see the end). -- */
  --radius:      6px;
  --radius-sm:   4px;
  --radius-lg:   10px;
  --radius-full: 9999px;
  --accent-bar:  3px;

  /* -- rhythm and sizing -- */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-12: 48px;
  /*
   * MEASURED DENSITY. Three of these five moved and two did not, and the
   * split is the point.
   *
   * NN/g measured sparse against dense pages of the same content: dense
   * (~8-14 items per screen, 17% whitespace) beat sparse (<7 items, 30%)
   * on findability AND on perceived transparency. Carbon's row scale is
   * Compact 24 / Short 32 / Default 48; at 14px body text Short is the
   * right rung, and 34px keeps a small control flush inside a cell.
   * Atlassian's between-components band is 12-24px, so 16 sits mid-band.
   *
   * `--control-h` and `--card-p` are NOT ours to tune: 42px buttons and
   * 22px card padding are measured off the original MKK application, which
   * is the stated reference. Compactness comes out of the
   * gaps BETWEEN things, never out of the anatomy of a card.
   */
  --row-h:        34px;
  --control-h:    42px;
  --control-h-sm: 34px;
  --card-p:       22px;
  --rhythm:       16px;
  --sidebar-w:    278px;
  --shell-max:    99rem;

  /* -- sidebar: the template's wine, flat -- */
  /*
   * THE RAIL IS THE SAME RED AS THE ACCENT, JUST DARKER.
   *
   * It used to be #4e0c11 — a brown-leaning wine, drawn from the old muted
   * accent. Beside the new #dc0005 the two read as two different brands: one
   * warm and earthy, one pure red, and the eye reads a hue disagreement long
   * before it can name it.
   *
   * #5a0206 is the same hue family at the SAME WEIGHT: relative luminance
   * .0223 against the old .0192, white text 14.5:1 against 15.2:1. So nothing
   * about the rail's presence on the page changes — only which red it is.
   */
  /*
   * MARKS AND METERS: colours that were living in rules instead of here.
   *
   * Nine coin chips, a meter segment and the danger button's hover edge were
   * written as literals down in the stylesheet. That is the drift to watch
   * for -- a colour the palette names, written by hand somewhere the
   * palette cannot reach -- and it is also why none of them was ever
   * measured: the contrast gate reads TOKENS. Named here, they are checked
   * (white sits on every coin chip) and they follow the theme.
   */
  --border-danger-hover:  #85686a;
  --meter-on:             #48566a;
  --coin-1:               #1f3a5f;
  --coin-2:               #2f5d50;
  --coin-3:               #6b4423;
  --coin-4:               #3d3a5c;
  --coin-5:               #5c5230;
  --coin-6:               #24505c;
  --coin-7:               #57304a;
  --coin-8:               #3f4a2a;
  --coin-9:               #45444a;
  /*
   * THE THEME PREVIEW CHIPS, AND WHY THESE FOUR DO NOT FOLLOW THE THEME.
   *
   * Every other colour here has a dark twin. These deliberately do not: a
   * chip showing what the LIGHT theme looks like has to stay light while the
   * reader is standing in the dark one, or the preview previews nothing.
   * They are tokens rather than literals so they are still greppable, still
   * in the palette, and still move as one if the two themes are ever
   * recalibrated.
   */
  --chip-light-page: #e9edf0;
  --chip-light-card: #ffffff;
  --chip-dark-page:  #0e141b;
  --chip-dark-card:  #1b2430;

  --sidebar-bg:      #8c1a12;
  --sidebar-bg-deep: #6d1310;

  /* -- type -- */
  --font-sans: "Segoe UI", Inter, system-ui, -apple-system, Arial, sans-serif;
  --font-mono: Consolas, "Cascadia Mono", ui-monospace, monospace;
  /* ONE STEP UP (2026-10-28): "çok minnak, incik cincik" - read by people past
     forty on office screens, the smallest text is 12px and the body 15px. */
  --fs-2xs: .75rem; --fs-xs: .8125rem;  --fs-sm: .875rem;
  --fs-base: .9375rem; --fs-md: 1rem; --fs-lg: 1.0625rem;   --fs-xl: 1.3125rem;
  --fs-2xl: 1.5625rem; --fs-3xl: 1.8125rem;

  /* -- shadows: a whisper on panels, drama only on hover lift -- */
  --shadow-card:    0 1px 2px rgba(15, 23, 42, .04);
  --shadow-lift:    0 12px 24px rgba(120, 22, 15, .14);
  --shadow-overlay: 0 24px 56px rgba(15, 23, 42, .18),
                    0 4px 12px rgba(15, 23, 42, .08);

  /* THE KEYBOARD RING IS TWO COLOURS, BECAUSE IT LANDS ON TWO SURFACES.
     Ink on paper measures 11.90:1 on the page and 14.01:1 on a card. The same
     ink on the red rail measures 1.52:1 — half of WCAG 1.4.11's 3:1 floor for
     a focus indicator, which is to say it was there and could not be seen.
     White on the rail measures 9.24:1 (8.03 hovered, 7.48 on the current
     page). Both are in the gate now; neither was before. */
  --focus-ring: #2c2b32;
  --focus-ring-rail: #ffffff;
  --speed: 140ms;
}

/* ==========================================================================
   THE SECOND PALETTE, AND WHY IT IS ONE LINE PER TOKEN

   Every colour above is repeated here with its dark twin beside it. Two
   values on one line rather than a second block, and the reasons are
   mechanical rather than aesthetic.

   FOLLOWING THE SYSTEM COSTS NOTHING. `color-scheme: light dark` makes
   light-dark() resolve off the reader's operating system, so "sistem" is
   the absence of a choice rather than a third code path. A stored choice
   wins on specificity alone -- :root[data-theme] beats :root -- with no
   ordering to get right and no !important anywhere.

   AND THE GATE CAN SEE IT. `bun run check` harvests the plain block above
   for the light palette and this one for the dark, then runs the SAME rule
   list twice. A second `[data-theme]` block would have been invisible to it:
   the harvest keeps the first definition of each name, so every ratio would
   have kept measuring the light palette while the dark one shipped
   unmeasured. That is the failure this shape exists to prevent.

   @supports IS THE SAFETY NET. A browser without light-dark() drops this
   whole block and gets exactly what shipped before -- light, and correct.
   Without the guard an unparseable declaration would leave var(--surface)
   unresolved and the page would render with no colours at all. The floor
   this raises is not new either: the stylesheet already needs color-mix()
   and :has(), both older than light-dark().

   The light value is now written twice, and that is the one thing that can
   drift -- so the gate asserts light-dark()'s FIRST argument equals the
   plain declaration above. Mechanical, exact, and it cannot be forgotten.
   ========================================================================== */
/*
 * THE TYPEFACE, AS FOUR ALTERNATIVES TO THE ONE ABOVE.
 *
 * Only `--font-sans` moves. `--font-mono` stays where it is: every number
 * column in the application is set in it with tabular figures, and the
 * contract screen's own faces (.ctr-font-*) describe somebody else's Word
 * document rather than this interface.
 *
 * NO FILE IS FETCHED. All five ship with Windows, which is where this hub
 * is read; the policy blocks an outside font host (`font-src 'self'`) and
 * the asset pipeline carries text, not bytes. Each stack names a fallback
 * for a machine that lacks the first choice, ending at the family the
 * default already trusts.
 *
 * THE SWATCH CARRIES THE ATTRIBUTE TOO, exactly as the colour swatch does,
 * so a sample of the face is drawn in the face itself.
 */
[data-font="calibri"] { --font-sans: Calibri, Carlito, "Segoe UI", system-ui, sans-serif; }
[data-font="corbel"]  { --font-sans: Corbel, "Segoe UI", system-ui, sans-serif; }
[data-font="tahoma"]  { --font-sans: Tahoma, Verdana, "DejaVu Sans", sans-serif; }
[data-font="cambria"] { --font-sans: Cambria, Georgia, "Times New Roman", serif; }
/* The default, written down so the preview swatch can wear it: `:root`
   already carries the same stack and the gate measures that they agree. */
[data-font="segoe"]   { --font-sans: "Segoe UI", Inter, system-ui, -apple-system, Arial, sans-serif; }

/* A sample of the face, in the face. Sized like a control so the five rows
   line up whatever the letters do. */
.font-chip {
  flex: none; display: grid; place-items: center;
  min-width: 96px; height: 36px; padding: 0 10px;
  border: 1px solid var(--border);
  background: var(--surface-sunken);
  font-family: var(--font-sans); font-size: var(--fs-md); color: var(--text-body);
}

@supports (color: light-dark(#000000, #ffffff)) {
  :root {
    color-scheme: light dark;
    --surface-page: light-dark(#e9edf0, #0e141b);
    --surface: light-dark(#ffffff, #1b2430);
    /* Koyu cukur yuzey kartla 1.096 idi — tabanin tam ustunde duruyordu.
       #0f1620 ile 1.161; uzerindeki soluk yazi 8.23'ten 8.72'ye cikiyor.
       Zeminle arasi daralıyor ama artik sayfanin uzerinde duran paneller
       --surface kullaniyor, yani o mesafe olculen sey degil. */
    --surface-sunken: light-dark(#f0f4f7, #0f1620);
    --surface-band-head: light-dark(#e8eff8, #243246);
    --surface-band-group: light-dark(#dbe6f2, #2e4360);
    --surface-control: light-dark(#ffffff, #1b2430);
    --surface-hover: light-dark(#e9eef3, #243040);
    --surface-selected: light-dark(#fbf1f1, #301f21);
    --surface-row-alt: light-dark(#f4f7f9, #1f2934);
    --surface-row-hover: light-dark(#e9eef3, #243040);
    /* Koyu bant #2d2123 iken kartla arasi 1.009 idi — yani bant diye bir
       sey yoktu. #3f2b2e ile 1.19; ustundeki en soluk yazi hala 6.31. */
    --surface-band: light-dark(#fdeceb, #3f2b2e);
    --text-body: light-dark(#182331, #e8eef4);
    --text-secondary: light-dark(#566475, #b6c2cf);
    --text-muted: light-dark(#606b7a, #a9b5c2);
    --text-icon: light-dark(#84909d, #8593a2);
    --text-on-accent: light-dark(#ffffff, #ffffff);
    --grid-line: light-dark(#182331, #c8d6e4);
    --border: light-dark(#ccd5de, #3a4655);
    --border-subtle: light-dark(#dde4ea, #2c3743);
    --border-input: light-dark(#8b95a1, #6f7d8c);
    --border-hover: light-dark(#687484, #93a1b0);
    --border-warm: light-dark(#dfbab5, #6d4c4c);
    --border-button: light-dark(#8b95a1, #6f7d8c);
    --border-danger: light-dark(#a38b8d, #8d6162);
    --surface-danger: light-dark(#fffafa, #261c1d);
    --accent: light-dark(#e0362a, #e0362a);
    --accent-solid: light-dark(#d12b20, #d12b20);
    --accent-hover: light-dark(#b91c1c, #b91c1c);
    --accent-active: light-dark(#97160f, #97160f);
    --accent-text: light-dark(#b91c1c, #f2897f);
    --accent-tint: light-dark(#fce3e0, #3c2120);
    --dept-general: light-dark(#e0362a, #e0362a);
    --dept-finance: light-dark(#6d4aa8, #a58bdd);
    --dept-treasury: light-dark(#0f6cbd, #4a9de0);
    --dept-marketing: light-dark(#a92a7f, #d47ab5);
    --dept-accounting: light-dark(#217346, #3f9e6d);
    --dept-legal: light-dark(#6e1b32, #cf7f97);
    --series-1: light-dark(#2563eb, #6b9cf5);
    --series-2: light-dark(#7e1820, #d9687a);
    --series-3: light-dark(#d4a106, #eab308);
    --ok: light-dark(#159565, #159565);
    --ok-solid: light-dark(#0f7a52, #0f7a52);
    --ok-tint: light-dark(#e4f6ef, #11261f);
    --ok-text: light-dark(#116e4a, #5fd7a4);
    --warn: light-dark(#aa6612, #aa6612);
    --warn-tint: light-dark(#fff4df, #2c2110);
    --warn-text: light-dark(#8a530e, #f0b45c);
    --error: light-dark(#9d1d25, #9d1d25);
    --error-tint: light-dark(#fdf3f3, #2e1618);
    --error-text: light-dark(#841219, #f39191);
    --info: light-dark(#0f6cbd, #0f6cbd);
    --info-tint: light-dark(#ecf3fa, #102435);
    --info-text: light-dark(#0b4e88, #7cbdf0);
    --sidebar-bg: light-dark(#8c1a12, #71140e);
    --sidebar-bg-deep: light-dark(#6d1310, #530f0a);
    --focus-ring: light-dark(#2c2b32, #e2e9f1);
    --focus-ring-rail: light-dark(#ffffff, #ffffff);
    --border-danger-hover: light-dark(#85686a, #a97374);
    --meter-on: light-dark(#48566a, #93a3b8);
    --coin-1: light-dark(#1f3a5f, #3f75c0);
    --coin-2: light-dark(#2f5d50, #41806e);
    --coin-3: light-dark(#6b4423, #a36735);
    --coin-4: light-dark(#3d3a5c, #736dad);
    --coin-5: light-dark(#5c5230, #837444);
    --coin-6: light-dark(#24505c, #397e90);
    --coin-7: light-dark(#57304a, #a75c8e);
    --coin-8: light-dark(#3f4a2a, #697b46);
    --coin-9: light-dark(#45444a, #75747e);
  }

  /* The stored choice, and the only thing it has to do is pin the scheme:
     every light-dark() above resolves from it. */
  :root[data-theme="light"] { color-scheme: light; }
  :root[data-theme="dark"]  { color-scheme: dark; }

  /*
   * THE INTERFACE COLOUR, AS FOUR COMPLETE SETS.
   *
   * Stablex red is `:root` above and needs no block; these are the
   * alternatives a person can pick on the preferences screen. Each one
   * replaces the WHOLE accent family - the fill, its hover and active
   * steps, the text grade, the tint a badge sits on, the focus ring, the
   * rail and the warm band - because half a family is a screen where the
   * button moved and the rail did not.
   *
   * AND EVERY ONE OF THEM IS MEASURED. `bun run check` harvests these
   * blocks by name and runs the SAME rule list over each preset in both
   * palettes: white on the fill, the text grade on three surfaces, the
   * badge on its own tint, the rail under the whole menu. A colour that
   * cannot be read cannot be offered, because the gate will not let it
   * be written down.
   *
   * They live INSIDE the light-dark() guard on purpose: a browser too
   * old for it gets the brand palette, which is correct and is what
   * shipped before there was a choice.
   */
  /*
   * THE BRAND, WRITTEN DOWN AS A PRESET TOO - and it has to be.
   *
   * :root already carries these values, so this block changes nothing on
   * <html data-accent="stablex">. It exists for the SWATCH: the preview chip
   * re-scopes the tokens by carrying the attribute itself, and the Stablex
   * chip carried none - so on a hub wearing Mor it inherited Mor and the
   * "Stablex" swatch was purple. A swatch that shows the wrong colour is
   * worse than no swatch.
   *
   * THE BRAND IS NOW IN TWO PLACES, so the gate measures that they agree:
   * `bun run check` compares this block against :root value by value. That
   * is the only reason this duplication is allowed to exist.
   */
  [data-accent="stablex"] {
    --accent: light-dark(#e0362a, #e0362a);
    --accent-solid: light-dark(#d12b20, #d12b20);
    --accent-hover: light-dark(#b91c1c, #b91c1c);
    --accent-active: light-dark(#97160f, #97160f);
    --accent-text: light-dark(#b91c1c, #f2897f);
    --accent-tint: light-dark(#fce3e0, #3c2120);
    --accent-ring: light-dark(rgba(224, 54, 42, .32), rgba(224, 54, 42, .38));
    --sidebar-bg: light-dark(#8c1a12, #71140e);
    --sidebar-bg-deep: light-dark(#6d1310, #530f0a);
    --surface-band: light-dark(#fdeceb, #3f2b2e);
  }
  [data-accent="lacivert"] {
    --accent: light-dark(#2563eb, #3b82f6);
    --accent-solid: light-dark(#1d4ed8, #1d4ed8);
    --accent-hover: light-dark(#1e40af, #1e40af);
    --accent-active: light-dark(#1e3a8a, #1e3a8a);
    --accent-text: light-dark(#1d4ed8, #9dbafc);
    --accent-tint: light-dark(#e5edfd, #1b2a48);
    --accent-ring: light-dark(rgba(37, 99, 235, .32), rgba(59, 130, 246, .38));
    --sidebar-bg: light-dark(#1e3a8a, #16306f);
    --sidebar-bg-deep: light-dark(#172c68, #102250);
    --surface-band: light-dark(#eaf0fd, #25334d);
  }
  [data-accent="zumrut"] {
    --accent: light-dark(#059669, #10b981);
    --accent-solid: light-dark(#047857, #047857);
    --accent-hover: light-dark(#065f46, #065f46);
    --accent-active: light-dark(#064e3b, #064e3b);
    --accent-text: light-dark(#047857, #6ee7b7);
    --accent-tint: light-dark(#dcf5e9, #10291f);
    --accent-ring: light-dark(rgba(5, 150, 105, .32), rgba(16, 185, 129, .38));
    --sidebar-bg: light-dark(#065f46, #054e3a);
    --sidebar-bg-deep: light-dark(#044a36, #03372a);
    --surface-band: light-dark(#e6f6ee, #203a31);
  }
  [data-accent="mor"] {
    --accent: light-dark(#7c3aed, #8b5cf6);
    --accent-solid: light-dark(#6d28d9, #6d28d9);
    --accent-hover: light-dark(#5b21b6, #5b21b6);
    --accent-active: light-dark(#4c1d95, #4c1d95);
    --accent-text: light-dark(#6d28d9, #c4b5fd);
    --accent-tint: light-dark(#eee9fe, #2a2141);
    --accent-ring: light-dark(rgba(124, 58, 237, .32), rgba(139, 92, 246, .38));
    --sidebar-bg: light-dark(#4c1d95, #3f1880);
    --sidebar-bg-deep: light-dark(#3b1676, #2d1160);
    --surface-band: light-dark(#f1ecfe, #332b4a);
  }
  [data-accent="antrasit"] {
    --accent: light-dark(#475569, #64748b);
    --accent-solid: light-dark(#334155, #334155);
    --accent-hover: light-dark(#1e293b, #1e293b);
    --accent-active: light-dark(#0f172a, #0f172a);
    --accent-text: light-dark(#334155, #cbd5e1);
    --accent-tint: light-dark(#e8edf3, #232c39);
    --accent-ring: light-dark(rgba(71, 85, 105, .32), rgba(100, 116, 139, .38));
    --sidebar-bg: light-dark(#1e293b, #16202e);
    --sidebar-bg-deep: light-dark(#0f172a, #0c131d);
    --surface-band: light-dark(#eef2f6, #2c3644);
  }

  /* PAPER IS WHITE WHATEVER THE SCREEN IS. Printing a dark theme puts pale
     ink on white paper and the page comes out looking empty -- one line
     here themes all of it, because every token resolves from the scheme. */
  @media print { :root { color-scheme: light; } }
}

/* The paper drawn in light ink. Same geometry, same opacity, same half-pixel
   inset that took five rounds to settle -- only the colour moves, and it is
   --grid-line's dark value so the pattern scan still recognises it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --paper-tile: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48'%3E%3Cpath d='M0 0.5H48M0.5 0V48' stroke='%23c8d6e4' stroke-opacity='0.09' stroke-width='1'/%3E%3C/svg%3E"); }
}
:root[data-theme="dark"] { --paper-tile: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48'%3E%3Cpath d='M0 0.5H48M0.5 0V48' stroke='%23c8d6e4' stroke-opacity='0.09' stroke-width='1'/%3E%3C/svg%3E"); }

/* ==========================================================================
   MOTION OFF, AS A READER'S CHOICE

   The six `prefers-reduced-motion` blocks in this file stay exactly as they
   are and keep serving the OPERATING SYSTEM's request. This is the separate
   switch on the preferences screen, and it is one rule rather than a seventh
   copy of six tuned blocks.

   THERE IS DELIBERATELY NO "ON" THAT DEFEATS THE SYSTEM SETTING. A reader
   whose computer asks for reduced motion gets it whatever this preference
   says. An application preference may add restraint; it may not remove an
   accessibility setting the person made once, for every program they use.

   `animation-duration: 1ms` rather than `animation: none`, and the difference
   matters in one place: the toast is `toast-in … , toast-out 400ms ease-in 7s
   forwards`. Killing the animation would kill the 7-second DELAY with it and
   the notification would sit on screen forever. Shortened, the delay survives
   and the message still clears itself -- which is exactly what the block at
   the toast's own reduced-motion rule already does by hand.

   Traced through every keyframe in this file: `enter` ends at opacity 1
   (`both` fill), `spin` stops, `hero-drift` parks at -900px which is one full
   tile of a 900px repeat-x pattern -- visually identical, and the reason 900
   was chosen. Only `progress-slide` needed a companion rule below: shortened,
   its 40%-wide bar parks at translateX(350%), i.e. off screen, and the
   progress feedback would silently disappear.
   ========================================================================== */
:root[data-motion="off"] *,
:root[data-motion="off"] *::before,
:root[data-motion="off"] *::after {
  animation-duration: 1ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 1ms !important;
}

/* The bar still has to say "something is happening" - the same shape the
   system-level rule already chose. */
:root[data-motion="off"] .progress.is-active::before {
  animation: none;
  width: 100%;
  opacity: .6;
}

/* -- reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
/* A CLASSED LIST STARTS AT ITS CARD'S EDGE. The line above clears margins,
   not the 40px start padding a browser gives every <ul> and <ol>, and
   `list-style: none` hides the bullet but keeps the gap. Measured in Edge:
   nine lists had 40px - the phase strip, the settings setup list, both
   legend strips, the quoted opinions, the release notes, the chat members,
   the message files and the support timeline - and all nine read 0px after
   this line, while the lists that set their own padding kept it. Zero specificity:
   a list that wants an indent (.manual-list) still sets its own, and an
   unclassed list inside prose keeps the browser's. */
:where(ul[class], ol[class]) { padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  /* KEEP THE SCROLLBAR'S ROOM WHETHER OR NOT THE PAGE SCROLLS. Moving from a
     long page (Pano) to a short one (Geri Bildirim) took the scrollbar away
     and every column jumped 15px sideways — measured: the content column was
     1259px on one page and 1274px on the next. */
  scrollbar-gutter: stable;
}
/* …except on the sign-in and bare error pages: one box in the middle of the
   screen, nothing to jump between, and the kept room showed as a 15px strip
   where the background stopped short of the window's edge. */
html:has(> body.login-page) { scrollbar-gutter: auto; }

body {
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  /* Carbon's rule: compact type lowers the LEADING, not the size. 14/20
     is its normal body set; 1.55 was looser than the reference. */
  line-height: 1.45;
  color: var(--text-body);
  background: var(--surface-page);
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
table { border-collapse: collapse; width: 100%; }

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/*
 * THE RAIL GETS ITS OWN RING, AND IT SITS INSIDE THE ROW.
 *
 * Two separate faults, reported as one: "tab ile selection".
 *
 * COLOUR — the ink ring measured 1.52:1 on the rail. It was drawn correctly
 * and could not be seen. White measures 9.24:1 there.
 *
 * PLACEMENT — rail rows run the full width of a 280px panel that scrolls
 * (`overflow-y: auto`), so a ring offset 2px OUTWARD had its left and right
 * sides outside the panel and clipped. Only the top and bottom lines
 * survived, which is exactly what the screen showed. Drawn 2px inward, the
 * whole rectangle is inside the row and the reader sees a box, not two
 * lines.
 *
 * Scoped to the rail rather than to `.sidebar-link`, so the back link, the
 * wordmark and anything added later are covered without being listed.
 */
.sidebar :focus-visible {
  outline-color: var(--focus-ring-rail);
  outline-offset: -2px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   Layout shell
   ========================================================================== */

.shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

/* THE SIDEBAR STANDS STILL WHILE THE PAGE SCROLLS.
   It scrolled away with the page before, which on the long screens (the pano,
   a card, settings) meant the module's own navigation was gone by the time
   you were halfway down and you had to scroll back up to leave the page.
   It is now viewport-tall and sticky.
   `align-self: start` is what makes that work: a grid item stretches to the
   row by default, and an item as tall as its row can never stick.
   Its own scrollbar (`overflow-y: auto`) appears ONLY when the menu itself is
   taller than the window - the earlier objection to this shape was two bars
   side by side, which is exactly what `auto` avoids when there is nothing to
   scroll. `overscroll-behavior: contain` stops a wheel over the menu from
   grabbing the page once the list has reached its end. */
/* A rail this tall as one flat colour reads as a painted strip. A long,
   shallow gradient down to the deeper step gives it a top and a bottom
   without anybody being able to point at where it changes. */
.sidebar {
  /*
   * A SHEET OF TINY SQUARES.
   *
   * Two attempts got this wrong before the description landed. First a sine
   * curve: the rail is 280px and a period does not fit in 280px, so it read
   * as a bent line that had been cut off. Then scattered dots: random
   * placement, and nothing in it "followed" anything.
   *
   * What was actually asked for is a grid — "birbirini takip eden küpler,
   * çarşaf gibi". Each square follows the next, and the pattern covers the
   * whole surface rather than sitting in one corner of it.
   *
   * A 20px tile with a 3px square, TILED — about 200 bytes, and the browser
   * repeats it. That is both smaller and more regular than drawing a hundred
   * shapes. Tier 1 of the research's cost table: static SVG, no script, no
   * animation frame, nothing to switch off for reduced motion.
   *
   * The half-bright second square on the opposite corner keeps a plain
   * repeat from reading as graph paper.
   */
  /* The rail contains its own layers and does not join the page's stack.
     It was load-bearing while a decorative layer sat here at z-index -1; that
     layer is gone (see the menu's motion block below for why), but a rail
     that is its own stacking context is the correct shape either way and
     costs nothing. */
  isolation: isolate;
  background-color: var(--sidebar-bg);
  /*
   * THE RAIL CARRIES NO PATTERN. One colour, one soft gradient down.
   *
   * It has been tried twice. A curve first: the rail is 280px and a sine
   * period does not fit in 280px, so it read as a cut-off wobbly line.
   * Then a sheet of 3px squares, which is what the comment here claimed for
   * a long time while the file still held the squeezed curve. Drawn
   * properly at last, the squares came back as "remove the white dots".
   *
   * So the answer is not a third pattern. THE PAPER IS THE CONTENT COLUMN'S
   * JOB and the rail's job is to be the one large calm red surface the
   * wordmark sits on; texture on both sides of that edge leaves the screen
   * with no quiet half. A single `background-image` also means no layer
   * list, so `repeat`, `position` and `size` stop needing a second value
   * each - the shape that let the curve hide behind an 18px tile.
   */
  background-image: linear-gradient(180deg, var(--sidebar-bg) 0%, var(--sidebar-bg-deep) 100%);
  background-repeat: no-repeat;
  color: var(--text-on-accent);
  display: flex; flex-direction: column; min-width: 0;
  position: sticky; top: 0; align-self: start;
  height: 100vh; height: 100dvh;
  overflow-y: auto; overscroll-behavior: contain;
  /* A hairline bar on the wine, not the OS default light one. */
  scrollbar-width: thin;
  scrollbar-color: rgb(255 255 255 / .22) transparent;
}
.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar::-webkit-scrollbar-thumb {
  background: rgb(255 255 255 / .22); border: 2px solid var(--sidebar-bg);
}
.sidebar::-webkit-scrollbar-thumb:hover { background: rgb(255 255 255 / .34); }
/*
 * THE BRAND BLOCK — a mark and a caption, not two competing lines.
 *
 * The first attempt dropped the real wordmark straight in where the old text
 * had been and kept the caption at the same size: two shouts, 2px apart, both
 * uppercase, jammed against the top of the rail. The mark is the brand; the
 * caption's job is to say quietly which application this is.
 *
 * So: more room above and below, a smaller mark, and a caption that steps
 * back to a hairline of tracking-wide small caps under it.
 */
/*
 * THE BRAND BLOCK: the mark on top, then a ruled caption band.
 *
 * Two rules and not one. A single line under the pair read as "the brand is
 * everything above this line" — which put the mark and the caption in the
 * same breath, at nearly the same weight. Ruled on BOTH sides, the caption
 * becomes its own thing: a label for the application, under the company's
 * mark rather than beside it.
 */
.sidebar-brand {
  padding: 24px 22px 0;
  border-bottom: 1px solid rgb(255 255 255 / .12);
}
/* The mark is 1920x444; this width decides its size and the intrinsic ratio
   does the rest. `display: block` removes the baseline gap an inline image
   would otherwise leave under it. */
/* Mesaj rayi da bu blogu tasiyor ve olcusunu BURADAN aliyor: her iki ray
   da 278px'lik ayni izgara sutunu, ve blok ayni sinifi giyiyor. "Tam ayni
   yer ayni boyutta" bir istekti; iki ayri dolgu sayisi yazmak onu ilk
   duzenlemede bozardi. */
.sidebar-brand img { display: block; width: 172px; height: auto; }
.sidebar-brand strong { display: block; font-size: var(--fs-lg); letter-spacing: .02em; }
/* The caption band. Negative side margins pull the rules out to the rail's
   full width, so they read as divisions of the panel rather than as a box
   drawn around a word. */
.sidebar-brand span {
  display: block;
  margin: 20px -22px 0; padding: 11px 22px;
  border-top: 1px solid rgb(255 255 255 / .12);
  border-bottom: 1px solid rgb(255 255 255 / .12);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: rgb(255 255 255 / .58);
}
/*
 * THE SAME BAND, OUTSIDE THE LINK — and it names the application you are in.
 *
 * It is not `.sidebar-brand span` because that span is the message rail's
 * "< Hub'a don" row, which has to stay inside the link. Here the text is the
 * module's name, and a link to the hub reading "Akit" would point at the
 * wrong page. `-plain` takes the rule off the wordmark block, because this
 * band draws both of them.
 */
.sidebar-brand-plain { padding-bottom: 20px; border-bottom: 0; }
.sidebar-caption {
  padding: 11px 22px;
  border-top: 1px solid rgb(255 255 255 / .12);
  border-bottom: 1px solid rgb(255 255 255 / .12);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: rgb(255 255 255 / .58);
}
/* Pushed to the floor of the flex column; never competes for attention. */
.sidebar-version {
  margin-top: auto; padding: 14px 22px;
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs);
  color: rgb(255 255 255 / .5); word-break: break-word;
}
/* The stamp is a link to the release notes. It keeps the quiet colour of the
   line it replaced — a foot-of-the-rail link that announced itself would be
   competing with the menu for no reason. */
.sidebar-version a { color: inherit; text-decoration: none; }
.sidebar-version a:hover { color: var(--text-on-accent); text-decoration: underline; }

/* The byline sits UNDER the build stamp and reads as a different kind of
   fact: not monospace, a little brighter, and given its own line. */
.sidebar-credit {
  display: block; margin-top: 6px;
  font-family: var(--font-sans); letter-spacing: .05em; font-size: 12px;
  color: rgb(255 255 255 / .62);
}

.sidebar-section {
  padding: 16px 22px 8px;
  font-size: var(--fs-xs);
  color: rgb(255 255 255 / .72);
}
.sidebar-nav { flex: 1; padding-bottom: 16px; }


/* ==========================================================================
   THE MENU'S MOTION — AND WHY IT IS HERE AND NOT IN THE RAIL ITSELF

   Three decorative animations were built into this rail and all three were
   rejected: a stepped band of light, a field of drifting dots, then pixels
   falling from the top. The fourth answer was not a fourth effect. It was
   reading what banks actually do:

     "Motion in fintech isn't decoration, it's direction. Every animation
      teaches users how information behaves."  (fintech design review, 2026)

     "Keep it subtle — a light background shift of 5-10% of your brand colour
      is plenty. A hover is a gentle nod, not a light show."  (sidebar UX)

   So the rail keeps its still texture and the motion moves to the only place
   it earns anything: the moment a person points at something. Three things
   move together, all under a sixth of a second:

     · the row lifts a little out of the rail (background)
     · a white edge GROWS from the middle of the row rather than appearing
     · the icon steps 2px toward the label

   The grow is the part that reads as quality. A border that switches on is a
   state; a border that arrives is an answer. It is a scaleY on a pseudo-
   element — a transform, so the compositor does it and the main thread is
   never involved.

   THE ACTIVE ROW DOES NOT ANIMATE. It has to be unmistakable the moment the
   page renders, not a moment later: somebody arriving on a screen should
   never have to wait to find out where they are.
   ========================================================================== */
.sidebar-link {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 22px; font-size: var(--fs-sm);
  color: rgb(255 255 255 / .80);
  position: relative;
  border-left: var(--accent-bar) solid transparent;
  transition: background var(--speed), color var(--speed);
}
/* The edge that grows. Drawn where the transparent border sits, so the row
   never moves sideways between states. */
.sidebar-link::before {
  content: "";
  position: absolute; left: calc(var(--accent-bar) * -1); top: 0; bottom: 0;
  width: var(--accent-bar);
  background: var(--text-on-accent);
  transform: scaleY(0);
  transition: transform var(--speed) ease-out;
}
.sidebar-link:hover { background: rgb(255 255 255 / .07); color: var(--text-on-accent); }
.sidebar-link:hover::before { transform: scaleY(1); }
.sidebar-link .icon { transition: transform var(--speed) ease-out; }
.sidebar-link:hover .icon { transform: translateX(2px); }

.sidebar-link[aria-current="page"] {
  background: rgb(255 255 255 / .12); color: var(--text-on-accent);
  border-left-color: var(--text-on-accent); font-weight: 600;
}
/* Already marked by the real border above; the pseudo-element would only
   double it. */
.sidebar-link[aria-current="page"]::before { content: none; }

/* How much is waiting, on the row that leads to it.

   WHITE ON THE RAIL, NOT THE ACCENT. The rail IS the accent, so an accent
   pill on it measures 1.5:1 and disappears; the same failure the focus ring
   had here. White on the rail measures 9.24:1 and is already in the gate.

   It pushes to the right edge and the label keeps the space it needs, so a
   count arriving does not re-wrap the row it sits on. */
/*
 * HOW MUCH IS WAITING, on the row that leads to it.
 *
 * The first version was a solid white disc with black figures — legible and
 * far too loud: a filled counter on a dark rail reads as an alarm, and this
 * is a tally of work, not a warning. It also sat at full brightness beside
 * menu rows drawn at 80% white, so it pulled the eye off the navigation it
 * was meant to annotate.
 *
 * A WASH OF THE RAIL'S OWN LIGHT instead — the same white-over-red the rows
 * use when a pointer crosses them, so the badge belongs to the surface it
 * sits on rather than being pasted onto it. The figures stay full white:
 * present, readable at a glance, and not shouting.
 *
 * IT KEEPS ITS SIZE WHATEVER THE NUMBER. `min-width` equal to the height
 * makes one digit a circle and two a short pill, so the row's right edge
 * does not shift as the count passes ten.
 */
.sidebar-count {
  margin-left: auto; flex: none;
  display: inline-grid; place-items: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--radius-full);
  background: rgb(255 255 255 / .16);
  color: var(--text-on-accent);
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.sidebar-link:hover .sidebar-count { background: rgb(255 255 255 / .26); }
.sidebar-link[aria-current="page"] .sidebar-count { background: rgb(255 255 255 / .22); }

/* A person who asked for less motion gets the states, not the travel. */
@media (prefers-reduced-motion: reduce) {
  .sidebar-link, .sidebar-link::before, .sidebar-link .icon { transition: none; }
  .sidebar-link:hover::before { transform: scaleY(1); }
}

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 0 28px; height: 72px;
  /* THE FROSTED STRIP FOLLOWS THE SURFACE, and used to be a hardcoded 94%
     white. In a dark theme that is a white bar with pale text on it -- the
     one literal in this file that broke a whole screen rather than a
     detail. color-mix keeps the translucency without naming a colour. */
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
  /*
   * THE FROSTING WAS NEVER APPLIED. The strip was left six percent
   * transparent for a blur that no rule ever asked for, so what actually
   * happened was bleed-through: scroll a page whose opener carries controls
   * and their ghosts slide visibly under the bar. Reported on the CMC preset
   * screen, where the preset chooser and the creation box appeared to sit on
   * top of the title.
   */
  backdrop-filter: saturate(140%) blur(10px);
}
/* No blur available means no translucency either - a bar you can read
   through is worse than one that is simply opaque. */
@supports not (backdrop-filter: blur(10px)) {
  .topbar { background: var(--surface); }
}
/* THE STICKY BAR EATS EVERY ANCHOR IT DOES NOT KNOW ABOUT.
   A `href="#panel"` scrolls the target to y=0, which is 72px UNDER this bar -
   so the heading you clicked is the one thing you cannot see when you arrive.
   It cost the guide's ten-item table of contents and the settings setup list.
   72px of bar + 16px of air. */
[id] { scroll-margin-top: 88px; }
/* The template's page-title: a 4px red bar standing beside the words. */
.topbar-title { display: flex; flex-direction: column; position: relative; padding-left: 19px; }
.topbar-title::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 4px; height: 36px; background: var(--accent);
}
.topbar-title span {
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.topbar-title strong { font-size: var(--fs-base); font-weight: 600; }
.topbar-user { display: flex; align-items: center; gap: 14px; font-size: var(--fs-sm); }

.main { padding: 24px; max-width: var(--shell-max); }
.main > * + * { margin-top: var(--rhythm); }

/* Page entry animation. CSS only, `both` fill — never a JS `initial` prop,
   which leaves the page permanently invisible if the script fails. */
/*
 * ARRIVING - 200ms, and a curve that decelerates.
 *
 * The measure is not taste: under 100ms reads as a jump, over 300ms reads as
 * waiting, and an entering element decelerates (`cubic-bezier(0.2, 0, 0, 1)`)
 * because that is what an object arriving somewhere does. The first version
 * of the second option ran 320ms over 18px on a springy curve and came back
 * as "olmamis" - it was a flourish, and a page turning is not an occasion.
 *
 * `fade` IS NOW A FADE. It used to also rise 6px, which made the name a small
 * lie and left no quiet option at all.
 */
@keyframes enter { from { opacity: 0; } to { opacity: 1; } }

/* THE ARRIVAL, AND ONLY AN ARRIVAL.

   A CLASS BECAME AN ATTRIBUTE, and that is the whole point of the change.
   This is a server-rendered application: every navigation is a fresh
   document, so this 220ms slide replayed on EVERY page load - including
   the ones that are not arrivals at all. Applying a filter, switching a
   tab, clearing a search: the reader stays on the same screen and the
   whole screen slides at them again. Reported exactly that way:
   "aslinda ayni sayfadayiz, neden kayiyor ki".

   `core/router.ts` strips `data-enter` when the request came FROM the
   same path it is going TO. An attribute is what makes that safe: it is
   one purpose-built token the router can remove, rather than a word
   inside a class list that some other rule might also be using. */
.main[data-enter] { animation: enter 200ms cubic-bezier(0.2, 0, 0, 1) both; }
@media (prefers-reduced-motion: reduce) { .main[data-enter] { animation: none; } }

/*
 * HOW A PAGE ARRIVES - the reader's choice, on <html>.
 *
 * `data-enter` on <main> says "this element animates"; `data-arrive` on <html>
 * says WHICH WAY. Two attributes because they answer two questions, and one
 * name for both would have read as a single setting with two homes.
 *
 * The default (absent) is the fade above. `reduced` motion still wins over
 * all of this: it is one rule on :root and it turns every animation off,
 * including these.
 */
@keyframes enter-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
:root[data-arrive="rise"] .main[data-enter] {
  animation: enter-rise 240ms cubic-bezier(0.2, 0, 0, 1) both;
}
:root[data-arrive="none"] .main[data-enter] { animation: none; }

/* ==========================================================================
   Page header
   ========================================================================== */

/* THE HERO, per the template: a white panel with a 4px red left bar, a red
   uppercase eyebrow, and a BIG tight title (29px, -0.04em). */
/*
 * THE HERO BAR FADES OUT DOWNWARD.
 *
 * A 4px block of a vivid red down the full height of a tall panel is a lot of
 * red, and it says the same thing at the bottom that it said at the top. Full
 * strength where the eyebrow and the title are, dissolved by the foot.
 *
 * `border-image` and not an extra element: this panel has ONE border, so a
 * gradient border-image has nothing else to overwrite. Where the property is
 * not supported the solid `border-left` above it still draws — the bar gets
 * less interesting, never absent.
 */
.page-head {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  flex-wrap: wrap;
  /*
   * THE LINE LIVES IN THE PANEL, NOT UNDER IT — AND NOW IT MOVES.
   *
   * The first attempt put this curve on the page background, and the
   * screenshot settled it: the content column is a wall of opaque white
   * cards, so a page background is glimpsed in 16px gutters and nowhere
   * else. The pattern was there and could not be seen.
   *
   * It is a LAYER now rather than this panel's background image, because a
   * background image cannot be moved by a transform — and transform is the
   * only way to move anything without repainting it on every frame.
   * See `.hero-wave` below.
   */
  position: relative; overflow: hidden; isolation: isolate;
  background-color: var(--surface);
  border-left: 4px solid var(--accent);
  border-image: linear-gradient(
      180deg,
      var(--accent) 0%,
      var(--accent) 34%,
      color-mix(in srgb, var(--accent) 22%, transparent) 78%,
      transparent 100%
    )
    1;
  box-shadow: var(--shadow-card);
  padding: 24px 30px;
}
.page-head h1 { font-size: 29px; line-height: 1.18; font-weight: 700; letter-spacing: -0.04em; }
.page-head .eyebrow {
  /* 11px, as every other small capital label: 10px was the smallest text
     in the hub and stood at the top of every page. */
  font-size: var(--fs-xs);
  color: var(--accent-text); font-weight: 800; margin-bottom: 6px;
}
.page-head p { color: var(--text-secondary); margin-top: 6px; font-size: 14px; line-height: 1.6; max-width: 780px; }
/*
 * THE HEADER ROW IS ONE LINE OF CONTROLS, SO ITS BOXES ARE ONE HEIGHT.
 *
 * `.field` is a block and a bare one holds a 34px input, while `.btn` is the
 * measured 42px. With the row stretching, the field grew to 42 and its input
 * stayed at the top of it: the preset chooser and the "Yeni preset adı" box
 * sat eight pixels high against the button beside them, which is what reads
 * as the button not being centred on them.
 *
 * Both halves are needed. The height makes the boxes match, and the centring
 * holds the row together when something in it is taller anyway - a field
 * carrying a hint or a refusal line underneath.
 */
.page-head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.page-head-actions .field-bare .control { height: var(--control-h); padding: 0 12px; }

/* ==========================================================================
   Card
   ========================================================================== */

/* The template's data-panel: a REAL 1px border and a whisper of shadow. */
.card {
  /* Inside a card, a panel recedes. */
  --panel-ground: var(--surface-sunken);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
/*
 * THE HEAD IS A NEAR-WHITE GREY, WITH A LINE UNDER IT.
 *
 * It was a warm band from "alt alta butun kartlar hep beyaz ya". Set beside
 * the original CMC release on 15.09 the bands read as pink blocks on every
 * screen, and as brown ones in the dark theme, and the user chose the
 * original's calmer layout: white, a title over a hairline. On 29.10 the
 * all-white card was again hard to read - its title ran into its content -
 * and the user asked for "gri veya beyaza yakın ama farklı tonlar": the
 * pane heads' cool --surface-band-head, not a warm hue.
 */
.card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px var(--card-p);
  background: var(--surface-band-head);
  border-bottom: 1px solid var(--border-subtle);
  flex-wrap: wrap;
}
/*
 * A CARD'S FIRST AND LAST PARTS FOLLOW ITS ROUNDED CORNERS (2026-10-29). A
 * card left unclipped (so a person list can open past it) had its head's
 * square ground painted over its rounded corners: a straight line seemed to
 * run over the card's top edge.
 */
.card > :first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; }
.card > :last-child { border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; }
.card-title { font-size: 17px; font-weight: 700; color: var(--text-body); }
.card-note { font-size: var(--fs-xs); color: var(--text-muted); }
/* A second line under a cell's main value (the journal's sicil under the
   name): always its own line, not beside a short name and under a long one. */
.cell-sub { display: block; }
.card-body { padding: var(--card-p); }
.card-body > * + * { margin-top: 12px; }
/* A CARD BODY THAT IS ALSO A ROW STACKS NOTHING - it lays side by side, and
   the vertical rhythm above pushed every neighbour 12px down. Centred in a
   flex row that reads as exactly 6px of misalignment; measured on the card
   opening screen ("Tümünü seç" at 622px, "Temizle" at 628px, both 34px
   tall). The same pair of classes meets on other screens, so the fix is
   here rather than in one module. */
.card-body.row > * + * { margin-top: 0; }
.card-foot {
  padding: 14px var(--card-p); border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap;
}
/* Accent bar on top — reserved for AT MOST ONE hero panel per page.
   It used to sit on every metric tile; four red bars in a row carry nothing. */
.accent-top { border-top: var(--accent-bar) solid var(--accent); }

/* ==========================================================================
   Metric cards
   ========================================================================== */

/* The original's metric: SEPARATE white cards with a 1px line, a
   sentence-case label, a BIG tight ink value. */
.metrics { display: grid; gap: 15px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
/*
 * FOUR TILES GO TWO BY TWO, NEVER THREE AND ONE.
 *
 * `auto-fit` at 220px fits four tiles only in a column of 4 x 220 + 3 x 15 =
 * 925px. Below that it puts three on the first row and the fourth ALONE under
 * them - seen on the CMC screen at 1180, where the column measured 838px: a
 * strip that reads as a strip, then an orphan. Beside the sidebar that is every
 * window up to about 1265px, and most strips in this application are exactly
 * four tiles (backup, CMC, MKK, volume, performance, five on projects).
 *
 * So the four-tile strip has its own steps: four across while four fit, two by
 * two below that, one column on a phone. Six have their own steps too (below);
 * every other count keeps `auto-fit`.
 */
@media (max-width: 1320px) {
  .metrics:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .metrics:has(> :nth-child(4):last-child) { grid-template-columns: minmax(0, 1fr); }
}
/*
 * SIX TILES GO THREE BY THREE (the reconciliation result).
 *
 * This comment used to say six "divide evenly at these widths". Measured in
 * headless Edge beside the sidebar, `auto-fit` put them 5 + 1 at 1600 and
 * 4 + 2 at 1440, 1366, 1100 and 1024: a strip with an orphan row under it.
 * Six across once six 220px tiles fit (a ~1395px column, a window of about
 * 1720px), three by three below that, two by three on a narrow window, one
 * column on a phone - the same 560px step as the four-tile strip.
 */
/*
 * FIVE TILES STAY ONE ROW while they fit, and go three over two below that.
 * `auto-fit` put Akit's comparison counts 4 + 1 at 1440 beside the sidebar —
 * the "change ratio" alone on a second row, reading as a separate thing.
 */
.metrics:has(> :nth-child(5):last-child) { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1100px) {
  .metrics:has(> :nth-child(5):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .metrics:has(> :nth-child(5):last-child) { grid-template-columns: minmax(0, 1fr); }
}
.metrics:has(> :nth-child(6):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (min-width: 1760px) {
  .metrics:has(> :nth-child(6):last-child) { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .metrics:has(> :nth-child(6):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .metrics:has(> :nth-child(6):last-child) { grid-template-columns: minmax(0, 1fr); }
}
/*
 * A TILE IS A WHITE CARD WITH A GREY LINE, as in the original
 * (html-release styles.css `.metrics article`).
 *
 * Every tile used to carry a red top bar and a red wash under it. Four red
 * bars in a row say nothing about four numbers; the user chose the plain
 * tiles on 15.09. The number is what the eye should land on.
 */
.metric {
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  padding: 20px 21px;
}
.metric .label {
  font-size: 13px; text-transform: none; letter-spacing: 0;
  color: var(--text-secondary); font-weight: 700;
}
.metric .value {
  margin-top: 14px; font-size: 25px; font-weight: 700; line-height: 1.15;
  letter-spacing: -0.045em;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
/* Values are INK in the original, not red - red is for accents. */
.metric .value .money { color: var(--text-body); font-family: var(--font-sans); }
/* AND THE EMPTY ONE TOO. `.num-empty` is monospace by default, which is right
   in a table column but wrong in a four-tile strip: three sans values beside
   one mono zero read as a rendering fault, not as "nothing yet". Grey already
   says that; the typeface only had to stop shouting. */
.metric .value .num-empty { font-family: var(--font-sans); }
/* The same on the board's cards: "%90,00" in grey monospace beside a bold
   "%100,00" read as two kinds of value. Grey says "not done yet"; the type
   stays the card's own. */
.board-card dd.num-empty { font-family: inherit; font-weight: inherit; }
/* #7b8793 measured 3.67:1 on white - under the floor, on the caption under
   every metric tile in the application. Invisible to the gate for the same
   reason as the green above: a literal is not a token. */
.metric .foot { margin-top: 5px; font-size: 12px; color: var(--text-muted); }

/* ==========================================================================
   Typography helpers

   The division of labour carried over from the ported apps: micro LABELS are
   uppercase, small, letter-spaced and muted; VALUES are monospace and
   emphasised. The label answers "what is this" and steps back; the eye lands
   on the value.

   Card titles are the EXCEPTION - sentence case, 16px. An uppercase card
   title shouts on a board of eighteen cards and wraps to two lines.
   ========================================================================== */

.label {
  font-size: var(--fs-xs);
  color: var(--text-muted); font-weight: 700;
}
.label-accent { color: var(--accent-text); }
.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Emphasised value: mono for alignment, INK for colour (the template keeps
   red for eyebrows/links; the numbers are dark). */
.money { font-variant-numeric: tabular-nums; color: var(--text-body); font-weight: 700; }
/* "No value yet" - visibly different from a zero. */
.num-empty { font-variant-numeric: tabular-nums; color: var(--text-icon); }
.muted { color: var(--text-muted); }
.small { font-size: var(--fs-sm); }
/*
 * A VALUE THAT WENT UP OR DOWN. Bold, and the SEMANTIC TEXT colour.
 *
 * Two faults were measured here, both of them invisible in a code review
 * and obvious in a screenshot of the volume table:
 *
 * 1. --ok and --error are MARK colours, not text colours. The palette says
 *    so a hundred lines up (--ok measures 3.81:1 on white, under the 4.5
 *    floor) and these two rules were the only place in the stylesheet that
 *    ignored it. A falling percentage was dark maroon at 12px and read as
 *    ordinary black text: the reader saw the minus sign, never the colour.
 * 2. --error is THE SAME HEX IN BOTH THEMES. On the dark surface a falling
 *    value was near-invisible, while the rising one stayed legible - so in
 *    the dark theme the table showed gains and hid losses.
 *
 * --ok-text and --error-text carry a second value for the dark theme and
 * are already measured against all three surfaces in both palettes by the
 * contrast scan, so neither fault can come back unnoticed.
 *
 * THE WEIGHT IS PART OF THE MEANING. Colour alone is not a signal (WCAG
 * 1.4.1): the sign or the arrow carries it for anyone who cannot separate
 * the two hues, and the bold face is what makes the pair readable at a
 * glance in a table of two hundred numbers. `flat` stays quiet on purpose
 * - no change is not news, and bolding it would make every row shout.
 */
.delta-up   { color: var(--ok-text);    font-weight: 700; font-variant-numeric: tabular-nums; }
.delta-down { color: var(--error-text); font-weight: 700; font-variant-numeric: tabular-nums; }
.delta-flat { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Table
   ========================================================================== */

.scroll-x { overflow-x: auto; }

/*
 * BOLUM ICINDEKI TABLONUN ZEMINI.
 *
 * `section()` bilerek yuzey cizmiyor: uzun bir sayfayi kart ustune kart
 * yigmadan bolmenin yolu bu. Ama govdesi bir TABLO oldugunda satirlar
 * dogrudan kareli zeminin uzerine dusuyor ve blok bir sey gibi okunmuyor —
 * bildirilen hali: "tablonun arkasi yok, ayirt edici degil".
 *
 * Kart icindeki tablolar bundan etkilenmiyor: oradaki zemin zaten kartin.
 */
.section-body > .scroll-x {
  background: var(--surface);
  border: 1px solid var(--border);
}

.table { font-size: var(--fs-sm); }
.table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface);
  padding: 10px 14px; text-align: left;
  font-size: var(--fs-xs);
  font-weight: 700; color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table tbody td {
  padding: 8px 14px; height: var(--row-h);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-body); vertical-align: middle;
}
.table tbody tr:hover td { background: var(--surface-row-hover); }
/* The row being looked at, in a list of its siblings (coin history). */
.table tbody tr.is-current td { background: var(--accent-soft, var(--surface-row-hover)); font-weight: 600; }
/* A row that opens its detail (table rowHref): the pointer says so. */
.js .table tbody tr[data-href] { cursor: pointer; }
/* "No rows" said inside the table, under its headers (table emptyRow). */
.table .table-empty-row td {
  padding: 28px 16px;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.table .table-empty-row:hover td { background: transparent; }

/*
 * A ROW THAT OPENS SOMETHING.
 *
 * The incoming-ticket queue drew its subject as a plain <a> and the cell's
 * own colour won: black text, no underline, no cursor — a table of headings
 * with no sign that any of them led anywhere, and the people whose job is
 * answering them could not tell there was anything to press.
 *
 * Three signals rather than one, because each covers where another fails:
 * the ink says "link" before the pointer arrives, the cursor says it on the
 * way, and the chevron says it on a touch screen where there is no pointer
 * at all.
 *
 * THE WHOLE ROW IS THE TARGET. `.row-open::after` is stretched over the row
 * it sits in, so the fifty pixels of empty cell beside a short subject are
 * as clickable as the words — the row is what a person is aiming at.
 * `:has()` is already the stylesheet's own tool (see .radio-option), and the
 * positioning it needs goes on the row rather than the cell so the area
 * covers all of it.
 */
/*
 * A NAME IN A TABLE IS TEXT THAT OPENS (2026-10-29): it was red, so a list of
 * eighty people was eighty red words and red stopped meaning "look here".
 * The page's own colour, bold; the accent and the underline on the pointer.
 */
.table a { color: var(--text-body); font-weight: 600; text-decoration: none; }
.table a:hover { color: var(--accent-text); text-decoration: underline; text-underline-offset: 2px; }
.table .col-nowrap { white-space: nowrap; }

/*
 * A FORM'S BUTTONS CLOSE IT AT THE RIGHT (2026-10-29), the primary last: the
 * same place on every screen. Rows that sit inside a line of fields (a
 * person picker, a grant row) are a field's neighbour, not the form's end.
 */
main form > .form-actions:last-child, main form > .row.form-actions:last-child, .user-form-save { justify-content: flex-end; }
.perf-person-picker > .form-actions, #grade-access form > .form-actions { justify-content: flex-start; }
.setup-pane .setup-step-body form.perf-person-picker > .form-actions:last-child { margin: 0; padding: 0; border-top: 0; }

/* The user's role decides which of the two is on screen. */
.user-form:has(select[name="role"] option[value="admin"]:checked) .role-member-only,
.user-form:has(select[name="role"] option[value="member"]:checked) .role-admin-only { display: none; }

/*
 * A CARD'S STEP BAR BELONGS TO ITS STEP (2026-10-29): under "Notlar" or
 * "Akran görüşü" it still offered "Kaydet ve onaya gönder" for a sheet out of
 * sight. It stands with "Bu adım" and its evidence ("Bağlam") only.
 */
.desk-card:has(#kart-akran:not([hidden])) .pane-foot,
.desk-card:has(#kart-notlar:not([hidden])) .pane-foot,
.desk-card:has(#kart-defter:not([hidden])) .pane-foot,
.desk-card:has(#kart-ilerleme:not([hidden])) .pane-foot { display: none; }
/* Two panels side by side in a card's tab: one height. */
.desk-card .tab-panel { align-items: stretch; }
/* A date and time in the card's ledger stays on one line. */
#kart-defter .table td:first-child { white-space: nowrap; }

.table tbody tr:has(.row-open) { position: relative; cursor: pointer; }
.row-open::after { content: ""; position: absolute; inset: 0; }
/* Anything the stretched area would swallow has to sit above it — a badge is
   only a label, but a button in a later column would stop working. */
.table tbody tr:has(.row-open) .badge,
.table tbody tr:has(.row-open) .btn { position: relative; z-index: 1; }

/* The mark at the end of the row: the same chevron the home tiles use for
   "Uygulamayı aç", so "this opens" is one gesture across the application. */
/* It is an <a>, so the table link rule above would give it the accent and
   an underline; what it needs is to look like a mark and behave like a
   link. The markup takes it out of the tab order — the subject link ahead
   of it already reaches this page, and two stops for one destination is
   one too many. */
.row-open-mark {
  display: flex; justify-content: flex-end;
  color: var(--text-icon); font-weight: 400; text-decoration: none;
}
.row-open-mark:hover { text-decoration: none; }
.table tbody tr:hover .row-open-mark { color: var(--accent-text); }
.table tbody tr:last-child td { border-bottom: 0; }
.table.striped tbody tr:nth-child(even) td { background: var(--surface-row-alt); }
.table.striped tbody tr:nth-child(even):hover td { background: var(--surface-row-hover); }
/* A column holding one avatar and nothing else. `width: 1px` is not a
   width - in an auto table it means "as narrow as the content allows", so
   the picture does not steal room from the name beside it. */
.table thead th.cell-avatar,
.table tbody td.cell-avatar { width: 1px; padding-right: 4px; }
/* Right-align numbers with a data-num attribute on the cell. */
.table [data-num] { text-align: right; font-variant-numeric: tabular-nums; }
/* Total band - the last row inside tbody, NOT a tfoot. These rules only
   target thead th / tbody td, so a tfoot would render unpadded and
   unbordered: the exact way a hand-written table starts looking broken. */
/* THE CLOSING BAND. It used to live inside <tbody>, so it inherited the body
   cell rules by accident; in <tfoot>, where it belongs, it needs them named.
   Without this the total row lost its padding and stepped out of the card. */
.table tfoot td,
.table tfoot th {
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface-head);
  font-weight: 700;
}
.table tbody tr.total td,
.table tfoot tr.total td { background: var(--surface-head); font-weight: 700; }
.table tbody tr.total:hover td { background: var(--surface-head); }

@media (max-width: 1440px) { .table thead th, .table tbody td { padding-inline: 12px; } }
@media (max-width: 1300px) { .table thead th, .table tbody td { padding-inline: 10px; } }

/* ==========================================================================
   Badge
   ========================================================================== */

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: var(--radius-sm);
  font-size: var(--fs-2xs);
  font-weight: 700; white-space: nowrap;
}
.badge-neutral { background: var(--surface-sunken); color: var(--text-secondary); }
.badge-ok      { background: var(--ok-tint);       color: var(--ok-text); }
.badge-warn    { background: var(--warn-tint);     color: var(--warn-text); }
.badge-error   { background: var(--error-tint);    color: var(--error-text); }
.badge-info    { background: var(--info-tint);     color: var(--info-text); }
.badge-accent  { background: var(--accent-tint);   color: var(--accent-text); }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: var(--control-h); padding: 0 16px;
  border: 1px solid transparent; border-radius: var(--radius); cursor: pointer;
  font-size: var(--fs-sm); font-weight: 600; white-space: nowrap;
  transition: background var(--speed), border-color var(--speed), color var(--speed);
}
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn:hover:not(:disabled) { transform: translateY(-1px); }
.btn-primary   { background: var(--accent-solid); color: var(--text-on-accent); }
.btn-primary:hover:not(:disabled)   { background: var(--accent-hover); }
.btn-secondary { background: var(--surface); border-color: var(--border-button); color: var(--text-body); }
.btn-secondary:hover:not(:disabled) { background: var(--surface-hover); border-color: var(--border-hover); }
.btn-ghost     { background: transparent; color: var(--text-secondary); }
.btn-ghost:hover:not(:disabled)     { background: var(--surface-hover); }
/* Danger is OUTLINED in the template - a destructive act should be read,
   not just coloured. */
.btn-danger    { background: var(--surface-danger); border-color: var(--border-danger); color: var(--error-text); }
.btn-danger:hover:not(:disabled)    { background: var(--error-tint); border-color: var(--border-danger-hover); }
/* A BARE FIELD MAKES THE WHOLE ROW SMALL, and the button comes along.

   `hideLabel` draws a 34px control (.field-bare below); a plain button is 42px.
   Put them in the same flex row and nothing lines up: in `.row` the 8px splits
   into a 4px overhang top AND bottom, so neither edge meets. It was reported
   as "buttons are different sizes" on two screens, and the count only ever
   grows, because every new filter bar repeats the pairing.

   SO IT IS FIXED HERE RATHER THAN AT THE CALL SITES (.claude/rules/arayuz.md:
   an alignment problem is solved in the token or the component). Passing
   `small: true` at the three sites would fix today and miss the fourth screen
   somebody writes next month. `.btn` covers `linkButton` too - it renders the
   same class list. */
.btn-sm,
.row:has(> .field-bare) > .btn,
.search-bar:has(> .field-bare) > .btn,
.pick-search > .btn { height: var(--control-h-sm); padding: 0 10px; font-size: var(--fs-xs); }
.btn-icon { width: var(--control-h-sm); padding: 0; }

/* ==========================================================================
   Forms
   ========================================================================== */

.field { display: block; }
.field > .label { display: block; margin-bottom: 6px; }
/* THE HINT GOES UNDER THE FIELD, always. It is a `<span>`, so it only ever
   looked like a block because `.control` filled the whole line; give an input
   a max-width and the hint quietly slides up beside it. */
.field-hint { display: block; margin-top: 4px; font-size: var(--fs-xs); color: var(--text-muted); }

/*
 * A FIELD THAT WAS REFUSED SAYS SO WHERE IT IS.
 *
 * `is-invalid` was already being set on controls by three components — and
 * there was no rule for it anywhere, so marking a field invalid did nothing
 * at all. Every refusal reached the person as one fading line at the top of
 * the page, which on the card screen can be two thousand pixels away from the
 * box that caused it.
 */
.control.is-invalid {
  border-color: var(--error);
  box-shadow: inset 0 0 0 1px var(--error);
}
.control.is-invalid:focus { outline-color: var(--error); }
.field-error {
  display: block; margin-top: 4px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--error-text);
}

.control {
  width: 100%; height: var(--control-h); padding: 0 12px;
  background: var(--surface-control);
  border: 1px solid var(--border-input); border-radius: var(--radius);
  color: var(--text-body);
  transition: border-color var(--speed), box-shadow var(--speed);
}
.control:hover:not(:disabled) { border-color: var(--border-hover); }
/* Quiet at rest, unmissable on focus. */
.control:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-tint);
}
.control:disabled { background: var(--surface-sunken); color: var(--text-muted); cursor: not-allowed; }
textarea.control { height: auto; padding: 10px 12px; resize: vertical; line-height: 1.5; }
select.control { cursor: pointer; }
.control-end { text-align: right; }

.checkbox { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }

.form-row { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
/* A ROW OF SHORT NUMBERS. 220px is the width a labelled text box needs;
   four page margins and a tolerance are five two-character numbers, and at
   220px each they wrapped to four plus a lonely fifth - a row that lined up
   with nothing above it. They are one group and are laid out as one. */
.form-row-tight { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
/* ROWS HAD NO GAP BETWEEN THEM AT ALL - measured 0px, twice, on the period
   form. What looked like breathing room was the trailing space of whichever
   field happened to carry a two-line hint; a row of plain fields sat flush
   against the next row's labels, and the calendar buttons touched the heading
   underneath them. The gap inside a row is 14px, so the gap between rows has
   to be at least that or the grid reads as one block. */
.form-row + .form-row,
.form-actions + .form-row { margin-top: 16px; }
/* ...AND THE SAME BETWEEN ANY TWO STACKED BLOCKS OF A FORM. The rule above
   only reaches two form-rows that touch; measured on the projects task form,
   four of its five boundaries had something else in between (a bare textarea,
   a lone select, the save row) and stayed at 0px.

   GAP, NOT `* + *`. The sibling version was tried and broke the volume fetch
   row: `<form><input type="hidden"><button></form>` - the hidden input takes
   no space but IS a sibling, so the button got pushed 16px down and stood out
   of line with the button beside it. A grid does not lay out `display:none`
   children at all, so the gap simply is not created for them.

   `:not([class])` is the guard, not a shortcut: EVERY classed form in this
   codebase is a one-line flex or grid bar (`.filters`, `.period-switch`,
   `.row`, `.col`), and turning one of those into a column would wreck it. A
   form that stacks its fields carries no class. */
/* NOT A HIDDEN ONE. An author `display` beats the browser's own `[hidden]`
   rule, so this line used to DRAW every classless `<form hidden>` as an empty
   grid - and the page rhythm then gave each one 16px. Measured on the CMC
   presets screen, whose chooser and refresh are such forms: 49px between the
   help strip and the panes where every other screen has 16. */
form:not([class]):not([hidden]) { display: grid; gap: 16px; }
/* A grid item's default `min-width: auto` lets a wide child (a scrolling
   table) push past the page instead of scrolling inside its own box. */
form:not([class]) > * { min-width: 0; }
/* A lone button is a grid item too, and grid items stretch: without this the
   save button would run the whole width of the card. */
form:not([class]) > .btn { justify-self: start; }
/* AND THE GRID OWNS THE SPACING, ALONE. `.form-row + .form-row` and
   `.form-actions` still carry their own margin-top for the few places that
   are not inside a column form; inside one they stacked ON TOP of the gap and
   made it 32px. Measured on nine screens before this line existed. */
form:not([class]) > .form-row,
form:not([class]) > .form-actions { margin-top: 0; }
/* A DATE STANDING ALONE IS NOT A FULL-WIDTH FIELD. Inside a `.form-row` it
   shares the row's rhythm and must stretch with its neighbours; as a direct
   child of a column form there is no neighbour, and the plan screen gave
   "Son tarih" a 1213px box for a ten-character value. Measured on nine
   screens: this is the only field it touches - the others are textareas and
   long selects, which are right at full width. */
form:not([class]) > .field > .control[data-date-field], form:not([class]) > .field > .date-wrap { max-width: 260px; }
/* TEK ALAN BIR SATIRI DOLDURMAZ. auto-fit tek cocuga butun genisligi
   veriyordu: iki secenekli bir acilir kutu 1200 piksele yayiliyor, yanindaki
   dortlu satirla ayni ritmi tutmuyordu. Kutunun boyu iceriginin boyu kadar
   olmali. */
/* A SOLITARY FIELD IS NOT A FULL-WIDTH FIELD. Alone in a row it stretched to
   the card's whole 1200px, so a one-line title got a box built for a
   paragraph. 560px is about a half row: wide enough for a sentence, and it
   still lines the field up with the two-column rows above and below it. */
.form-row > .field:only-child,
.form-row > .field-static:only-child { max-width: 560px; }
/*
 * SUZGEC CUBUGU DA BIR CUBUK.
 *
 * Bunu bir kez cozmustuk: donem secici "kagidin uzerinde duran, yarim
 * cizilmis bir sey" gibi okunuyordu ve altindaki .period-switch kurali onu
 * ince bir yuzeye oturttu. Ayni sey suzgec cubuklari icin de gecerliydi ve
 * onlara yapilmamisti - kart disinda duran her suzgec, havada duran birkac
 * kutu gibi goruluyordu.
 *
 * Kartin ICINDEKI suzgecler dokunulmuyor: orada zemin zaten kartin, ve
 * uzerine ikinci bir yuzey koymak kart icinde kart olurdu.
 */
.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
/*
 * BIR IPUCU KENDI KONTROLUNU YUKARI KALDIRMAMALI.
 *
 * Olculdu (/accounting, 1600, SHOT_MEASURE_SELECTOR=".field"):
 *
 *     Sablon ara : ust=344  yukseklik=64
 *     Kategori   : ust=344  yukseklik=64
 *     Gorunum    : ust=323  yukseklik=85     <-- 21px yukarida
 *
 * Ustteki kural kutularin ALTINI hizaliyor: 344+64 = 408, 323+85 = 408.
 * Ipucu, alanin kutusunun icinde kontrolun altinda durdugu icin, kutular
 * altindan hizalaninca ipuclu KONTROL komsularinin 21px ustune cikiyor.
 * Suzgec cubugunda hizalanmasi gereken sey kutu degil KONTROL.
 *
 * Bu yuzden ipucu kendi kutusunun yuksekligine sayilmiyor, altina asiliyor;
 * cubuk da yalniz bir ipucu VARSA altinda yer ayiriyor.
 *
 * `flex-start` OLMAZ: gonder dugmesi `.control-end` icinde ve ustunde etiket
 * yok, etiket hizasina cikardi. Sabit bir etiket payi da olmaz: cubuk 1180'de
 * satir kiriyor (goruldu) ve etiket iki satira dustugu anda pay yanlis olur.
 */
.filters .field { position: relative; }
/*
 * VE IPUCU TEK SATIR. Ilk deneme sabit 32px yer ayirdi; 1180'de ipucu IKI
 * satira dustu (olculdu: cubuk 311+88 = 399'da bitiyor, ipucu 390+35 = 425'te)
 * ve alttaki kartin uzerine bindi. Sabit bir pay dogru olamaz: sayi ekran
 * genisligine, cumlenin uzunluguna ve yazi tipine bagli.
 *
 * Suzgec ipucu kisa bir yan nottur. Tek satira sigmiyorsa yeri kontrol cubugu
 * degil, sayfanin kendi yardim seridi (`pageHelp`) - ve bu ekranlarin hepsinde
 * o serit zaten var. Tam cumle `title` olarak erisilebilir kaliyor.
 */
.filters .field > .field-hint {
  position: absolute; top: 100%; left: 0; right: 0;
  margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.main > .filters,
.section-body > .filters {
  padding: 11px 15px;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
/*
 * IPUCUNUN YERI BU BLOGUN ARDINDA AYRILIR, ve sebebi olculdu.
 *
 * Ayni kural once `.filters`in hemen ardina yazilmisti ve HIC UYGULANMADI:
 * yukaridaki `padding` KISAYOLU ayni ozgullukte (0,2,0) ve dosyada daha sonra
 * geldigi icin her seferinde `padding-bottom`u sifirliyordu. Olcum soyledi -
 * cubuk 88px cikiyordu (11 + 64 + 13), yani pay 32 degil 13'tu, ve ipucu kendi
 * cubugunun 8px disina sarkiyordu.
 *
 * Simdi hem SONRA geliyor hem de ayni iki baglami adiyla hedefliyor (0,3,0).
 */
.main > .filters:has(.field-hint),
.section-body > .filters:has(.field-hint) { padding-bottom: 32px; }

/* THE PERIOD SWITCHER IS A BAR, NOT A LOOSE FORM.
   It used to render as a bare label + select + button standing directly on the
   paper - on "Performans Karnem" it was the only thing on the page outside a
   card, and it read as something half-drawn. One thin surface, one line: the
   word, the period, the button. */
.period-switch {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  padding: 11px 15px;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
  font-size: var(--fs-sm);
}
.period-switch-label {
  font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted);
}
.period-switch .field { min-width: 260px; }
.period-switch .control { height: var(--control-h-sm); padding: 0 10px; }
/* INSIDE A CARD IT NEEDS NO SURFACE OF ITS OWN. The bar exists so the switcher
   is not left standing on the paper; on the settings screen it opens the
   "Donem" card, where a second white frame inside a white frame is one border
   too many. Same line, no box - and flush left with the fields beneath it. */
.card-body > .period-switch:first-child {
  background: none; border: 0; box-shadow: none; padding: 0 0 16px;
}

/* ==========================================================================
   Alerts and empty states
   ========================================================================== */

/* THE ICON STANDS BESIDE THE SENTENCE, NOT ABOVE IT. The rule had no layout
   of its own, and the icon is a block, so every alert in the application
   drew its mark on one line and its words on the next: measured on the CMC
   settings screen, icon at 408px, text at 423px, in a 54px box for a
   one-line message. A row puts the mark on the first line of text; the 1px
   nudge centres a 15px icon on that 17px line. */
.alert {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 14px; border-left: var(--accent-bar) solid;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm); font-weight: 600;
}
.alert > svg { flex: none; margin-top: 1px; }
/* The body may carry a list as well as a sentence (components.ts alert). A
   list inside the box speaks in the box's own colour and weight, without the
   card rows' hairlines. */
.alert-body { min-width: 0; }
.alert-body > * + * { margin-top: 6px; }
.alert-body ul { list-style: disc; padding-left: 18px; }
/* `ul li`, one step more specific than `.plain-list li`, which comes later in
   this file and would otherwise draw its row hairlines inside the box. */
.alert-body ul li { padding: 2px 0; border: 0; font-weight: 500; color: inherit; }
.alert-body a { color: inherit; text-decoration: underline; }
.alert-error { background: var(--error-tint); border-left-color: var(--error); color: var(--error-text); }
.alert-warn  { background: var(--warn-tint);  border-left-color: var(--warn);  color: var(--warn-text); }
.alert-ok    { background: var(--ok-tint);    border-left-color: var(--ok);    color: var(--ok-text); }
.alert-info  { background: var(--info-tint);  border-left-color: var(--info);  color: var(--info-text); }

/* Bos durum kutusu: sayfada beyaz, kartin icinde geri cekilmis. */
.empty {
  background: var(--panel-ground); border: 1px solid var(--border);
  padding: 32px 20px; text-align: center; color: var(--text-muted);
}
.empty strong { display: block; color: var(--text-secondary); font-size: var(--fs-lg); margin-bottom: 4px; }

/* ==========================================================================
   Status card - the current state of the system, not a section heading.
   The left rule carries the STATUS colour, set by a modifier class so it
   never collides with the brand accent.
   ========================================================================== */

.status {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--text-muted);
  box-shadow: var(--shadow-card); padding: 20px var(--card-p);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap;
}
/* The text column takes the room beside the mark. Without a basis a long
   detail line wrapped the whole column under the mark (Akit's KVKK verdict,
   which lists every unanswered question), leaving the mark alone on a row. */
.status > .grow { flex: 1 1 320px; min-width: 0; }
.status-ok    { border-left-color: var(--ok); }
.status-warn  { border-left-color: var(--warn); }
.status-error { border-left-color: var(--error); }
.status-busy  { border-left-color: var(--info); }
.status strong { display: block; font-size: var(--fs-lg); font-weight: 600; }
.status p { color: var(--text-secondary); font-size: var(--fs-sm); margin-top: 2px; }

/* ==========================================================================
   Home menu tiles
   ========================================================================== */

.tiles { display: grid; gap: var(--rhythm); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* ==========================================================================
   ARRANGING THE HUB

   The order belongs to the reader, so the screen that changes it says so:
   a handle on everything that moves, and two steps beside it. The steps are
   the mechanism - they work with the script blocked, a keyboard reaches
   them, and a single tap is the alternative to dragging that WCAG 2.5.7
   asks for. The drag is the feel laid on top.
   ========================================================================== */

/* Nothing here is text to be selected: a drag that paints a blue
   selection across three tiles is the gesture going to the wrong
   place. The headings stay readable, they just do not highlight. */
.layout-edit { user-select: none; }
.tile-group { display: block; }
/* The rule above each heading already spaces the groups; a second margin
   here doubled the gap and the page read as five detached screens. */
.tile-group + .tile-group { margin-top: 0; }
/*
 * THE HEADING AND ITS RULE, THE SAME SHAPE AS THE CARD STRIP.
 *
 * It used to be a title with a grey hairline under it, stretched to the full
 * width — the same mark every heading in the application carries, so five
 * departments read as five paragraphs of one page rather than as five
 * groups. What separates them now is what separates the controls under a
 * card: a rule that starts where the words end.
 *
 * THE RULE IS THE DEPARTMENT'S OWN COLOUR. Each section carries its
 * `tile-*` class (routes/home.ts), so `--tile-color` is in scope here and
 * the line above a row of Hazine cards is the blue those cards are. The
 * accent is the fallback, which is what an unclassified group already uses.
 *
 * `order` PUTS THE RULE IN THE MIDDLE. A pseudo-element on a flex container
 * is laid out as its first or last item, and what is needed is between the
 * title and the tools — so the rule takes order 1 and the tools order 2.
 * The alternative was an empty <span> in the markup whose only job is to be
 * a line.
 */
.group-head {
  display: flex; align-items: center; gap: 12px;
  margin-top: calc(var(--rhythm) * 1.35);
}
.group-head .section-title {
  flex: none; min-width: 0;
  /* The rule beside it replaces the one under it; keeping both drew a
     corner. */
  padding-bottom: 0; border-bottom: 0;
}

/*
 * THE RULE FADES OUT, IT DOES NOT RUN INTO THE MARGIN.
 *
 * A flat 2px bar the width of the page was the first attempt and it read as
 * a barrier: heavy at the far end, where there is nothing to divide, and
 * loudest exactly where the eye has already left the heading. The same
 * mistake .page-head was fixed for — its accent edge fades down the panel
 * rather than stopping dead — so this follows that, along the line instead
 * of down it.
 *
 * IT STARTS AT THE CONTROLS, NOT AT THE PAGE EDGE. The handle and arrows sit
 * beside the words they belong to; the rule is what carries the eye away
 * from them. With the controls parked at the right margin the heading and
 * its tools were two unrelated things at opposite ends of a line.
 *
 * 2px AT THE HEAD, dissolved by two thirds of the way across. Thin enough
 * not to compete with the cards under it, present enough to say where one
 * department stops.
 */
.group-head::after {
  content: ""; order: 2; flex: 1 1 0; min-width: 16px; height: 2px;
  background: linear-gradient(
    90deg,
    var(--tile-color, var(--accent)) 0%,
    color-mix(in srgb, var(--tile-color, var(--accent)) 45%, transparent) 38%,
    transparent 72%
  );
}
.group-head .move-tools { order: 1; }

/* The first heading on the page does not push away from a heading above it. */
.layout-edit > .tile-group:first-of-type > .group-head,
.tile-group:first-of-type > .group-head { margin-top: 0; }

.move-tools { display: inline-flex; align-items: center; gap: 2px; flex: none; }
/* Each step is its own form, and a form is a block: without this the two
   arrows stack instead of sitting side by side. */
.move-form { display: inline-flex; }

/*
 * DRAGGING IS THE ANSWER; THE ARROWS ARE THE OTHER ANSWER.
 *
 * They were drawn beside every handle at full strength and the screen read as
 * a form with arrows rather than as something you pick up and move - which is
 * what came back ("oklar degil de drag olucakti"). They are still here,
 * still in the tab order, still a real form post: they are what a keyboard
 * reaches, what works with the script blocked, and the single-tap alternative
 * to dragging that WCAG 2.5.7 requires. They simply stop shouting.
 *
 * THE ROW KEEPS ITS HEIGHT. Fading rather than removing means nothing on the
 * page moves when a pointer passes over it.
 *
 * AND WITH NO SCRIPT THEY ARE ALWAYS THERE, because then they are not the
 * other answer - they are the only one.
 */
/*
 * THE ARROWS ARE ALWAYS THERE.
 *
 * They used to sit at `opacity: 0` and appear under the pointer. Two things
 * were wrong with that. A control nobody can see is a control nobody knows
 * exists — on a screen whose entire purpose is rearranging, the way to
 * rearrange was hidden. And a faded button still takes its space, so every
 * strip carried an invisible box the size of two buttons: the gap people
 * kept finding beside the handle.
 *
 * THE END OF A LIST SHOWS ONE DIRECTION. Position decides it, not markup,
 * so a drag that rearranges the list without reloading gets the right
 * arrows the instant the DOM order changes.
 */
/* A LIST OF ONE HAS NOWHERE TO PUT ITS ONLY CARD, so it gets no strip —
   not one with both arrows hidden and a handle that cannot move anything.
   Decided here rather than when the page was built, because a drag can make
   a list of one into a list of two without reloading: the department that
   received the card had drawn its own tile alone, with no controls, and it
   stayed that way beside a neighbour that had them. */
.tiles > .tile-slot:only-child .move-tools { display: none; }

.tiles > .tile-slot:first-child .move-form[data-move="up"],
.tiles > .tile-slot:last-child .move-form[data-move="down"],
/* THE GROUP RULES STOP AT THE HEADING. Written as a plain descendant
   selector they reached into the section and took the matching arrow off
   every CARD inside it too — the first department lost every "previous" it
   had, so its last card was left with a handle and nothing else. A section
   is first; the cards within it are not. */
.layout-edit > .tile-group:first-of-type > .group-head .move-form[data-move="up"],
.layout-edit > .tile-group:last-of-type > .group-head .move-form[data-move="down"] { display: none; }

/*
 * THE HANDLE. `touch-action: none` is not decoration: without it the browser
 * claims the first finger movement for scrolling and the drag never starts on
 * a touch screen.
 */
.drag-grip {
  display: grid; place-items: center; flex: none;
  width: 28px; height: 28px;
  /* The one thing in the strip you PICK UP, so it is the one thing drawn at
     full strength. The arrows are the same action one step at a time. */
  color: var(--accent); cursor: grab;
  touch-action: none; user-select: none;
}
.drag-grip:hover { color: var(--accent-hover); }
.drag-grip:active { cursor: grabbing; }
/* No script, no drag - and then a handle is a promise nothing keeps. */
html:not(.js) .drag-grip { display: none; }

.tile-slot { display: flex; flex-direction: column; gap: 0; min-width: 0; }
/* The card takes the height; the strip under it is whatever it needs. This
   is what lines every strip in a row up on one edge even when one card runs
   to three lines of description and its neighbour runs to one. */
.tile-slot .tile { flex: 1; }

/*
 * THE CONTROL STRIP: A RULE WITH THE CONTROLS SET INTO IT.
 *
 * The first attempt drew a bordered, filled box under every card — a second
 * panel hanging off the first, which is heavier than the card it belongs to
 * and reads as a separate thing. What was asked for, and what is right, is a
 * line: the rule runs out to both edges and the buttons sit in the gap it
 * leaves, the way a divider carries a label.
 *
 * THE LINE IS TWO PSEUDO-ELEMENTS, one either side, each taking the space
 * the buttons do not. That is what centres the controls no matter how many
 * of them there are — one arrow at the end of a list, two in the middle —
 * with nothing to keep in step by hand.
 *
 * THE ACCENT, NOT THE DEPARTMENT COLOUR. Everything here is an action on the
 * card; the department is what the card IS. Colouring the controls per
 * department would give the same button five meanings.
 */
.tile-slot .move-tools {
  align-items: center; gap: 6px;
  margin-top: 10px; padding: 0;
  border: 0; background: none;
}
.tile-slot .move-tools::before,
.tile-slot .move-tools::after {
  content: ""; flex: 1 1 0; min-width: 8px; height: 2px;
  background: var(--accent);
}

/* Prominent, because this row IS the screen while it is on it. The ghost
   button's muted ink disappeared against the card underneath. */
/*
 * HOVER IS A GLOW ON THE GLYPH, AND NOTHING ELSE MOVES.
 *
 * Two versions were wrong before this one. A pale tint behind a dark red
 * icon was two low-contrast states a few percent apart, so the button read
 * as smudged rather than touched. A solid accent square was legible and
 * far too loud: three of them in a strip under every card turned the menu
 * into a row of pressed buttons, and the card itself stopped being the
 * thing on screen.
 *
 * A GLOW IS ALREADY THIS APPLICATION'S ANSWER for "the pointer is here" —
 * it is what the tiles do, and for the same reason the hard outline was
 * taken off them: a box that snaps into existence around a small control is
 * a rectangle appearing, not a response. `drop-shadow` follows the drawn
 * path rather than the element's box, so what lights up is the arrow.
 *
 * THE BOX STAYS EMPTY. No background, no border, no size change — nothing
 * that could shift the strip or its neighbours by a pixel while a pointer
 * crosses it.
 *
 * `color-mix` and not a literal rgba, so changing the accent changes the
 * glow with it; a literal here would drift from it.
 */
.move-tools .btn { color: var(--accent-text); background: none; }
.move-tools .btn .icon,
.drag-grip .icon {
  transition: filter var(--speed), color var(--speed);
}
.move-tools .btn:hover,
.move-tools .btn:focus-visible { background: none; color: var(--accent); }
.move-tools .btn:hover .icon,
.move-tools .btn:focus-visible .icon {
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--accent) 65%, transparent));
}

/* The handle is already drawn at full accent, so its glow is the whole
   change — and it stays lit for as long as the card is being held. */
.drag-grip:hover .icon,
.is-dragging .drag-grip .icon {
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--accent) 70%, transparent));
}

/* A person who asked for less motion gets the state, not the fade. */
@media (prefers-reduced-motion: reduce) {
  .move-tools .btn .icon,
  .drag-grip .icon { transition: none; }
}

/*
 * THE LIFTED ONE.
 *
 * The offset arrives as a custom property the script sets; everything that
 * is a LOOK - the lift, the shadow, the scale - stays here, which is what the
 * interface rule asks for. `pointer-events: none` lets the pointer read the
 * element underneath, which is how the drop target is found at all.
 */
/*
 * THE CARD BEING HELD. TRANSLATION ONLY — NO SCALE.
 *
 * It used to lift by 2%, and that 2% was a bug with a nice name. Every
 * animation here works by measuring where a card IS and moving it from
 * there (FLIP), and a scaled box measures larger than the card's layout
 * slot: on a 300px card that is six pixels of disagreement between what was
 * measured and where it lands. The result was a small, final jump at the
 * end of an otherwise smooth drop — reported, correctly, as the card
 * teleporting the last moment.
 *
 * The lift is still there. It is the shadow and the stacking order, which
 * are what actually say "this one is off the page"; the scale was saying it
 * a second time and charging six pixels for it.
 */
.is-dragging {
  position: relative; z-index: 5;
  transform: translate(var(--drag-dx, 0px), var(--drag-dy, 0px));
  box-shadow: var(--shadow-lift);
  pointer-events: none;
}

/*
 * THE CARDS THAT ARE MAKING ROOM.
 *
 * The transition lives on the LIST rather than on the cards, and only while
 * a drag is running: on the cards it would also catch the page's arrival
 * animation and every card would glide in from wherever the previous page
 * had left it.
 *
 * The held card is exempt. It is following a finger in real time, and a
 * transition on that is the difference between a card you are holding and a
 * card that is swimming after you.
 */
.is-sorting > [data-drag-item] { transition: transform 200ms cubic-bezier(0.2, 0, 0, 1); }
.is-sorting > [data-drag-item].is-dragging { transition: none; }

/*
 * THE CARD ON ITS WAY DOWN. Stacking, and nothing else.
 *
 * It has just lost .is-dragging, which is what let it follow a finger with
 * no transition — keeping that on would make the landing instant. What it
 * must keep for the length of the flight is its place in the stack: it is
 * travelling over its neighbours, and underneath them it would disappear
 * behind a card and reappear.
 *
 * No transform and no transition of its own: the flight is one inline
 * transform and the transition the list is already lending every card.
 */
.is-settling { position: relative; z-index: 5; }


}
@media (prefers-reduced-motion: reduce) {
  .is-sorting > [data-drag-item] { transition: none; }
}
/* Where it came from, while it is away. */
.is-drag-origin { opacity: .35; }

/* An icon with no word beside it - the word is still there, for a screen
   reader and for the pointer's tooltip. Square, so a row of them reads as
   one control rather than as buttons of drifting width. */
.btn-icon { padding: 0; width: var(--control-h-sm); flex: none; }
.btn-icon.btn-sm { width: 28px; height: 28px; }


.tile {
  display: flex; flex-direction: column; min-height: 164px;
  padding: var(--card-p);
  background: var(--surface);
  /*
   * THE EDGE IS THE TILE'S OWN COLOUR, mixed down to a hairline.
   *
   * It was `--border-warm` (#dfbab5, a pink), which is right for the red
   * departments and wrong for every other one: a Hazine card carried a blue
   * top bar, a blue chip, a blue "Uygulamayı aç" — and a pink outline. The
   * hover glow two rules below already reads `--tile-color`; the resting
   * edge disagreeing with it was the mismatch.
   *
   * 34% keeps it a hairline rather than an outline. A full-strength border
   * would frame ten cards in ten colours and turn the menu into a paint
   * chart; the bar at the top is where the department is stated.
   */
  border: 1px solid color-mix(in srgb, var(--tile-color, var(--accent)) 34%, var(--border));
  border-top: 3px solid var(--tile-color, var(--accent));
  box-shadow: var(--shadow-card);
  position: relative; overflow: hidden;
  /* `outline-color` gitti: artik ortada bir outline yok. */
  transition: transform var(--speed), box-shadow var(--speed);
}
/*
 * A SOFT GLOW, NOT A HARD RING — and the old one really was broken.
 *
 * It was `outline: 3px solid`, and an outline's WIDTH cannot be transitioned;
 * only `outline-color` can. So the 3px band appeared at full width the
 * instant the pointer arrived and merely faded in colour: a hard rectangle
 * snapping into existence around the card. Reported as "buglu", and it was.
 *
 * `box-shadow` transitions completely, and it takes as many layers as the
 * effect needs. Three:
 *   · a hairline that says exactly where the card ends,
 *   · a blurred halo that is the glow,
 *   · the lift the card already had.
 *
 * THE GLOW IS THE TILE'S OWN COLOUR, not the accent. Each tile already
 * carries its department in `--tile-color` — the top bar, the icon chip and
 * the "Uygulamayı aç" link all read it. A hover that ignored it would light a
 * blue card in red and say, wrongly, that the colour means nothing.
 *
 * `color-mix` and not a literal, so a department that changes colour changes
 * its glow with it; a literal rgba here would drift from it.
 * The fallback is the accent, which is what an unclassified tile already uses
 * for its bar.
 */
a.tile:hover {
  transform: translateY(-3px);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--tile-color, var(--accent)) 38%, transparent),
    0 0 18px 2px color-mix(in srgb, var(--tile-color, var(--accent)) 20%, transparent),
    var(--shadow-lift);
}
.tile-head { display: flex; align-items: center; gap: 12px; }
.tile-icon {
  display: grid; place-items: center; width: 36px; height: 36px; flex: none;
  background: var(--tile-color, var(--accent)); color: var(--text-on-accent);
  border-radius: var(--radius-sm);
}
.tile-dept { font-size: var(--fs-2xs); color: var(--text-muted); font-weight: 700; }
.tile h3 { margin-top: 16px; font-size: var(--fs-lg); font-weight: 600; }
.tile p {
  margin-top: 6px; font-size: 13px; line-height: 20px; color: var(--text-secondary);
  /* Three lines, not two: one module's sentence needs the third at every
     width under 1920 and ended in "…" on the first screen people see. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.tile-foot {
  margin-top: auto; padding-top: 14px; border-top: 1px solid var(--border-subtle);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.tile-open { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 700; color: var(--tile-ink, var(--tile-color, var(--accent))); }
.tile-flat { box-shadow: none; border: 1px solid var(--border); border-top-width: 1px; }

/* ==========================================================================
   Login
   ========================================================================== */

/*
 * THE FRONT DOOR GETS THE PAPER TOO.
 *
 * This screen is the one place in the application with nothing on it — a
 * centred box on an otherwise empty grey field — and it was the only screen
 * that carried none of the app's own texture. The graph paper and the curve
 * are the same two layers the content column uses, anchored to the BOTTOM so
 * they sit under the box rather than behind the fields.
 *
 * SAME TILE, SAME OPACITY, AND IT MOVES WITH IT. This is the one screen with
 * nothing else on it, so a paper nobody can see leaves it genuinely empty -
 * see the measurement in the `.main-col` note.
 */
.login-page {
  min-height: 100vh; display: grid; place-items: center; padding: 24px;
  /* The drifting layer is a child at a negative z-index, so this element has
     to be the stack it lives in. */
  position: relative; overflow: hidden; isolation: isolate;
  background-color: var(--surface-page);
  /*
   * THE PAPER STOPS BEFORE THE CURVE DOES.
   *
   * Two textures meeting at full strength is where a background starts
   * looking like two backgrounds. The grid fades out on the way down, so
   * the lower third of the screen belongs to the curve alone and the
   * bottom edge of the page is empty rather than crosshatched.
   *
   * A GRADIENT LAYER, NOT A MASK - and for the same reason the hero's fade
   * lives inside its SVG: `mask` on an element makes it a backdrop root and
   * changes how everything inside it composites. This is `<body>`. A stop
   * of the page colour painted OVER the grid costs one gradient and changes
   * nothing about the box.
   *
   * The first image in the list paints on top, so the fade is written
   * first and the paper second - the same order the content column uses.
   */
  background-image:
    linear-gradient(180deg, transparent 40%, var(--surface-page) 86%),
    var(--paper-tile);
  background-size: auto, 48px 48px;
  background-repeat: no-repeat, repeat;
  background-position: left top, left top;
}

/* ==========================================================================
   THE LOGIN SCREEN'S DRIFTING LINE

   The hero's tile and the hero's keyframes, placed across the foot of the
   page. Same seamless loop, same one transform, same measured cost — a
   second effect here would have been a second thing to keep true.

   It fades UPWARD to nothing well below the box, so the two fields and the
   button never have anything moving behind them. Decoration's one hard rule.
   ========================================================================== */
.login-wave {
  /* THE DRAWING IS 132px TALL AND IS DRAWN 132px TALL.

     It was 46vh with a height of `100%`, which stretched a 132px drawing to
     460px on a normal screen — the same curve at three and a half times the
     amplitude, with the stroke fattened to match. It read as a different,
     much louder thing than the one on the home screen, and the difference
     was scale alone.

     The band is taller than the tile so the fade has somewhere empty to
     happen; the tile itself sits on the floor at its own size. */
  position: absolute; left: 0; right: 0; bottom: 0; height: 232px;
  z-index: -1; overflow: hidden; pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, transparent 8%, #000 52%);
          mask-image: linear-gradient(180deg, transparent 8%, #000 52%);
}
.login-wave::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0;
  width: calc(100% + 900px);
  background-color: var(--accent);
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='132' fill='none'%3E%3Cpath d='M0,80.7L10,81.3L20,81.6L30,81.8L40,81.8L50,81.7L60,81.4L70,81L80,80.6L90,80L100,79.4L110,78.7L120,78.1L130,77.4L140,76.7L150,76L160,75.3L170,74.7L180,74.1L190,73.6L200,73.1L210,72.6L220,72.1L230,71.7L240,71.3L250,70.9L260,70.5L270,70L280,69.6L290,69.1L300,68.5L310,67.8L320,67.1L330,66.2L340,65.3L350,64.2L360,63.1L370,61.7L380,60.3L390,58.7L400,57.1L410,55.3L420,53.4L430,51.4L440,49.3L450,47.2L460,45.1L470,42.9L480,40.8L490,38.7L500,36.6L510,34.6L520,32.8L530,31.1L540,29.5L550,28.2L560,27L570,26.1L580,25.4L590,25L600,24.8L610,24.9L620,25.3L630,26L640,26.9L650,28.1L660,29.5L670,31.2L680,33.1L690,35.2L700,37.5L710,40L720,42.6L730,45.2L740,48L750,50.8L760,53.6L770,56.4L780,59.1L790,61.8L800,64.3L810,66.8L820,69.1L830,71.2L840,73.2L850,74.9L860,76.5L870,77.9L880,79L890,80L900,80.7' stroke='%23e0362a' stroke-opacity='0.34' stroke-width='1.5'/%3E%3Cpath d='M0,96.8L10,95.5L20,94.1L30,92.8L40,91.5L50,90.2L60,89L70,87.8L80,86.6L90,85.5L100,84.4L110,83.4L120,82.4L130,81.5L140,80.7L150,80L160,79.3L170,78.7L180,78.2L190,77.8L200,77.4L210,77.2L220,77.1L230,77L240,77L250,77.2L260,77.4L270,77.7L280,78.1L290,78.6L300,79.2L310,79.8L320,80.6L330,81.4L340,82.2L350,83.2L360,84.2L370,85.3L380,86.4L390,87.6L400,88.8L410,90L420,91.3L430,92.6L440,93.9L450,95.2L460,96.5L470,97.9L480,99.2L490,100.5L500,101.8L510,103L520,104.2L530,105.4L540,106.5L550,107.6L560,108.6L570,109.6L580,110.5L590,111.3L600,112L610,112.7L620,113.3L630,113.8L640,114.2L650,114.6L660,114.8L670,114.9L680,115L690,115L700,114.8L710,114.6L720,114.3L730,113.9L740,113.4L750,112.8L760,112.2L770,111.4L780,110.6L790,109.8L800,108.8L810,107.8L820,106.7L830,105.6L840,104.4L850,103.2L860,102L870,100.7L880,99.4L890,98.1L900,96.8' stroke='%23e0362a' stroke-opacity='0.24' stroke-width='1.1'/%3E%3C/svg%3E");
  mask-repeat: repeat-x;
  mask-size: 900px 132px;
  mask-position: left bottom;
  animation: hero-drift 48s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .login-wave::before { animation: none; }
}

/* The mark takes the accent like everything else — see ui/icons.ts for why it
   is `currentColor` and not a literal. */
.logo { color: var(--accent); }
.login-box { width: 100%; max-width: 380px; }
/* The door's light/dark switch: the same corner the topbar keeps it in. */
.login-theme { position: absolute; top: 16px; right: 16px; }
.login-brand { text-align: center; margin-bottom: 22px; }
/* A brand panel, not a floating mark. `--accent` and not `--accent-solid`
   because nothing here is text the contrast floor covers: a logotype is
   exempt (WCAG 1.4.3), and this is the one place the true brand red belongs
   at full strength. */
/*
 * THE WORDMARK IN INK, PAINTED THROUGH ITS OWN SHAPE.
 *
 * The file is white — it is drawn for the red rail — and on this pale page a
 * white mark is invisible. The first answer was a red panel behind it, which
 * worked and was still a box drawn around a logo.
 *
 * A MASK inverts the relationship: the SVG supplies the SHAPE (its alpha
 * channel is exactly the letterforms) and CSS supplies the colour. So there
 * is still ONE logo file, and its colour on this page is `--text-body` — a
 * token, not a second asset that would drift the day the ink moves.
 *
 * `brightness(0)` on an `<img>` would also have produced black, in one line.
 * It produces PURE black, which is not this application's ink and would have
 * been the darkest thing on the page.
 */
.login-mark { display: block; width: 244px; margin: 0 auto 16px; }
.login-mark svg { display: block; width: 100%; height: auto; }
/*
 * A CSS `fill` BEATS the `fill="#f9faf9"` written on each path: a
 * presentation attribute loses to any rule. So the file stays exactly as the
 * company draws it and the page decides the colour — which is a token, not
 * pure black. Black would be the darkest thing on this page and darker than
 * the application's own ink.
 */
.login-mark svg path { fill: var(--text-body); }
.login-brand strong { display: block; font-size: var(--fs-2xl); font-weight: 700; letter-spacing: .02em; }
/*
 * THE POTENTIAX WORDMARK IN INK, the same way as the company mark above: the
 * white PNG supplies the shape (its alpha channel), the token the colour.
 * 768x320 is the file's own ratio.
 */
/* Under the company mark and narrower than it: Stablex leads, PotentiaX is its app. */
.product-ink {
  display: block; width: 150px; aspect-ratio: 768 / 320; margin: 16px auto 0;
  background-color: var(--text-body);
  -webkit-mask: url("/potentiax-logo.png") center / contain no-repeat;
  mask: url("/potentiax-logo.png") center / contain no-repeat;
}
.login-brand span { display: block; margin-top: 6px; font-size: var(--fs-xs); color: var(--text-muted); }
.login-box .card-body > * + * { margin-top: 14px; }

/* ==========================================================================
   Utilities - a deliberately tiny set. If something needs more, it gets a
   named class instead of a pile of utilities in the markup.
   ========================================================================== */

.row   { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/*
 * BIR HUCREDEKI IKI DUGME ALT ALTA GECMEZ.
 *
 * 1180'de sablon tablosunun "Bos indir" / "Ornekli indir" ciftleri alt alta
 * duserek her satirin boyunu ikiye katliyordu; seviye rozeti ve sayilar da iki
 * satirlik bir hucrenin ortasinda asili kaliyordu. Sebep `.row`un kendi
 * `flex-wrap: wrap`i.
 *
 * KURAL BILEREK DAR: hucrenin METNINE dokunmuyor. Bir tablo hucresine en son
 * `nowrap` uygulandiginda 962px'lik bir hucre ve uygulamanin tek yatay tasmasi
 * cikmisti (1165px'e karsi 1319px - bu dosyadaki .board-fields notu). Burada
 * yalniz DUGME cifti sarilmiyor; dar ekrani tablonun kendi `.scroll-x`i
 * cozuyor.
 */
.table td > .row { flex-wrap: nowrap; }
.col   { display: flex; flex-direction: column; gap: 10px; }
.grow  { flex: 1 1 auto; min-width: 0; }
.right { text-align: right; }
.stack > * + * { margin-top: var(--rhythm); }
.hidden { display: none !important; }

/* ==========================================================================
   Shell parts the layout needs
   ========================================================================== */

/* THE SKIP LINK IS GONE, AND IT WAS A REAL FEATURE.
   It let a keyboard user jump past the menu straight to the content — WCAG
   2.4.1 — and appeared only while focused. Removed on request: it surfaced on
   Tab as a red box over the brand and read as a fault rather than a tool.
   Bringing it back is this rule plus one line in `shell()`; if it returns it
   should be styled so it looks deliberate when it appears. */

/*
 * THE GRAPH PAPER, AND THE LINE DRAWN ON IT.
 *
 * The 48px grid is the template's own texture and half the character of the
 * original. What sits over it now is a plotted curve — three summed sines,
 * fading in and out down the band. It is not ornament chosen at random: this
 * application's whole subject is a number moving over days, and graph paper
 * with a line on it is the oldest way of saying that.
 *
 * THREE LAYERS, ONE ELEMENT, NO DOM. Backgrounds paint behind every
 * descendant by definition — so there is no absolutely-positioned decoration
 * layer, no negative z-index, no stacking context to get wrong, nothing for a
 * screen reader to announce and nothing to swallow a click. The alternative
 * (a positioned canvas at -z-10) is the arrangement that "renders but is
 * invisible" the moment its wrapper stops forming a stacking context.
 *
 * THE FADE IS INSIDE THE SVG, not a CSS mask. A mask would work and would
 * also make this element a backdrop root, changing how everything inside it
 * composites. A gradient on the stroke costs nothing and changes nothing.
 *
 * IT DOES NOT MOVE. Motion has to earn its place, and the job it would do
 * here is "look alive" — which is not one. People read tables on this page
 * all day; a drifting background is a cost they pay on every screen for a
 * flourish they stop noticing on the second. Static means there is also
 * nothing for prefers-reduced-motion to switch off.
 *
 * The first image in the list paints ON TOP, so the curve sits over the grid.
 * The topbar floats above both at 94% white.
 *
 * THE LINE IS A MEASUREMENT, NOT A TASTE - AND IT TOOK FOUR OF THEM.
 *
 * `.10` of #94a3b8, inherited from the original MKK stylesheet: 1.07:1.
 * That is the number this palette already learned to distrust once - card
 * against ground measured 1.08:1 and came back as "everything is white, I
 * cannot read it". Same blue-grey at `.28`: 1.22:1, still
 * reported as absent. The ink at `.18`: 1.42:1, still reported as absent.
 * The ink at `.34`: 2.04:1, seen at last - and reported as too strong.
 * Softening it to `.26` (1.70:1) changed nothing the reader could name.
 *
 * A 72px cell was tried and sent back: the MESH IS 48px, that part was never
 * the problem. What was wanted was the same paper, half as present.
 *
 * SO THE TWO DIALS ARE SET AGAINST EACH OTHER, and that is the whole idea.
 * A 48px cell draws half again as many lines as a 72px one, so keeping the
 * total weight of ink on the screen while going back to the finer mesh means
 * halving the line: `.09`, 1.18:1. Density and opacity are not two ways of
 * saying "stronger" - they multiply, and only their product is what the eye
 * calls loud.
 *
 * THIS IS THE FAINTEST VALUE THAT HAS EVER BEEN DELIBERATE HERE, and it is
 * only safe because the two rasterisation faults above are gone: with the
 * strokes inset half a pixel and antialiasing on, a pale line renders as a
 * pale line at every zoom instead of rounding away to nothing. `.10` used to
 * mean "sometimes absent"; `.09` now means `.09`.
 *
 * A background is only correct when it is BOTH - present, and quiet.
 *
 * Two things were wrong at once, which is why raising one number three
 * times did not fix it:
 *
 * COLOUR. A blue-grey line differs from this ground mostly in HUE, and a
 * ~1.2:1 luminance step cannot carry hue. The reader said "soft black grid"
 * in the first sentence; the ink was the answer and the opacity was not.
 *
 * RASTERISATION. The tile carried `shape-rendering='crispEdges'` AND drew
 * its lines on the tile boundary - a 1px stroke centred at x=0 spans -0.5
 * to +0.5, half of it outside the tile, and with antialiasing disabled the
 * rasteriser is free to round that to nothing. Below 100% page zoom the
 * whole line can vanish, silently, on one machine and not another. Both are
 * gone: the strokes are inset half a pixel (crisp at 1:1 without asking for
 * it) and antialiasing is back on, so at any scale the line softens rather
 * than disappears.
 *
 * FOUR ROUNDS OF "CANNOT SEE IT" IS THE LESSON, not the number: a decoration
 * that only reads on a lossless screenshot has not been checked, and a
 * number raised three times is a sign the wrong dial is being turned.
 */
.main-col {
  display: flex; flex-direction: column; min-width: 0;
  background-color: var(--surface-page);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1920' height='380' fill='none'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23e0362a' stop-opacity='0'/%3E%3Cstop offset='.5' stop-color='%23e0362a' stop-opacity='.2'/%3E%3Cstop offset='1' stop-color='%23e0362a' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M0,211.7L20,216.8L40,221.6L60,225.9L80,229.8L100,233.3L120,236.3L140,238.9L160,241.1L180,242.9L200,244.3L220,245.3L240,246.1L260,246.5L280,246.7L300,246.7L320,246.5L340,246.1L360,245.7L380,245.1L400,244.6L420,244L440,243.4L460,242.8L480,242.3L500,241.9L520,241.5L540,241.1L560,240.8L580,240.6L600,240.4L620,240.2L640,240L660,239.8L680,239.5L700,239.1L720,238.6L740,237.9L760,237L780,236L800,234.6L820,233L840,231L860,228.7L880,226.1L900,223L920,219.6L940,215.8L960,211.7L980,207.1L1000,202.3L1020,197L1040,191.5L1060,185.7L1080,179.7L1100,173.4L1120,167.1L1140,160.6L1160,154.2L1180,147.7L1200,141.4L1220,135.2L1240,129.3L1260,123.6L1280,118.3L1300,113.4L1320,108.9L1340,105L1360,101.6L1380,98.8L1400,96.7L1420,95.2L1440,94.3L1460,94.2L1480,94.7L1500,96L1520,97.9L1540,100.5L1560,103.7L1580,107.5L1600,111.8L1620,116.7L1640,122.1L1660,127.8L1680,133.9L1700,140.3L1720,147L1740,153.7L1760,160.6L1780,167.5L1800,174.4L1820,181.1L1840,187.8L1860,194.2L1880,200.3L1900,206.2L1920,211.7' stroke='url(%23g)' stroke-width='1.6'/%3E%3C/svg%3E"),
    /*
       THE PAPER RUNS OUT AT THE FOOT OF THE PAGE, and this stop sits
       BETWEEN the two drawings on purpose: above the grid, below the
       curve. The curve is at the top and stays whole; only the paper
       thins out, over the last third of however tall the document turns
       out to be. On a screen-high page that is a soft floor; on a long
       one it is a slope nobody notices, which is the point.
    */
    linear-gradient(180deg, transparent 65%, var(--surface-page) 100%),
    var(--paper-tile);
  background-size: 1920px 380px, auto, 48px 48px;
  background-repeat: repeat-x, no-repeat, repeat;
  background-position: center top, left top, left top;
}

.icon { flex: none; }

.sidebar-brand { display: block; }
.sidebar-back {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 22px; font-size: var(--fs-xs); font-weight: 700;
  color: rgb(255 255 255 / .62);
  border-bottom: 1px solid rgb(255 255 255 / .10);
}
.sidebar-back:hover { color: var(--text-on-accent); }
/* The count is the ONLY thing in a module rail that is not about that
   module, so it sits at the far end of the row instead of beside the
   words: a number pinned to the edge is read as a state, a number glued
   to a label is read as part of it. */
.sidebar-back .badge { margin-left: auto; }

/* Fotograf harflerin USTUNE biniyor; yuklenemezse altindaki harfler
   goruluyor, bos bir renkli daire degil. */
.avatar { position: relative; overflow: hidden; }
/* Profil ekranindaki fotograf satiri: gorsel, form ve kaldir yan yana. */
.photo-row {
  display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap;
  margin-top: 12px;
}
.photo-form { flex: 1; min-width: 240px; display: grid; gap: 10px; }

.avatar-photo {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.avatar {
  display: grid; place-items: center; width: 30px; height: 30px; flex: none;
  background: var(--accent-solid); color: var(--text-on-accent); border-radius: var(--radius);
  font-size: var(--fs-xs); font-weight: 700;
}
.topbar-who { display: flex; flex-direction: column; line-height: 1.25; }
.topbar-who strong { font-weight: 600; }
.topbar-who em { font-style: normal; font-size: var(--fs-2xs); color: var(--text-muted); }

/* A table fills its card edge to edge: the table supplies its own padding and
   a second one from the card would push the columns out of alignment with the
   card head above it. */
.card-flush { padding: 0; }
.card-flush > * + * { margin-top: 0; }

@media (max-width: 1100px) {
  .shell { display: block; }
  /* Below this width the sidebar is a horizontal strip across the top, so
     the viewport-tall sticky column above must be undone completely. */
  .sidebar {
    display: block; position: static;
    height: auto; overflow: visible;
  }
  .sidebar-brand { padding: 14px 20px; }
  .sidebar-brand span { display: none; }
  .sidebar-back { padding: 10px 20px; }
  .sidebar-section { padding: 9px 20px 3px; }
  .sidebar-nav { display: flex; flex: none; flex-wrap: wrap; padding: 4px 12px 8px; }
  .sidebar-link { border-left: 0; border-bottom: var(--accent-bar) solid transparent; padding: 9px 12px; }
  .sidebar-link[aria-current="page"] { border-left-color: transparent; border-bottom-color: var(--text-on-accent); }
  .topbar-who { display: none; }
}
/* A PHONE-WIDTH TOPBAR: at 390px the sign-out button ran ~40px past the
   screen on every page. The bar tightens, a long page title ends in an
   ellipsis, and the button keeps its icon — its word stays for screen
   readers (the same clipping as .sr-only). */
@media (max-width: 560px) {
  .topbar { padding: 0 16px; gap: 10px; }
  .topbar-title { min-width: 0; }
  .topbar-title strong, .topbar-title span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar-user { gap: 8px; flex: none; }
  .topbar-signout-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
}

/* ==========================================================================
   Remaining odds and ends
   ========================================================================== */

.section-title {
  font-size: var(--fs-xl); font-weight: 700; color: var(--text-body);
  padding-bottom: 8px; border-bottom: 1px solid var(--border-subtle);
}

/* Section header — how a long page divides itself WITHOUT stacking cards. */
.section-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 8px; border-bottom: 1px solid var(--border-subtle);
}
.section-head .eyebrow {
  display: block;
  font-size: var(--fs-xs);
  color: var(--accent-text); font-weight: 700; margin-bottom: 2px;
}
.section-head h2 { font-size: var(--fs-lg); font-weight: 600; }
.section-head .section-note { font-size: var(--fs-xs); color: var(--text-muted); }
.section-body { margin-top: 14px; }
/* BLOCKS INSIDE A SECTION ARE SPACED LIKE BLOCKS INSIDE A CARD. Nothing spaced
   them: measured on the CMC settings screen, the alert ended where the note
   began (452), the note where the next line began (469), and the test button
   where its report began (642); on the volume settings screen the excluded
   coins hint touched its list (823). Written this early in the file so a
   component's own, later margin still wins. */
.section-body > * + * { margin-top: 12px; }
.section + .section { margin-top: var(--sp-8); }

/* ==========================================================================
   The task list - the setup order, drawn.

   The number comes from a CSS counter on the <ol>, not from markup: the
   list stays correctly numbered when a step is conditional and never
   renders. The row that can be done NOW carries the 3px red left bar - the
   same "you are here" mark the hero uses - and it is the only row that is a
   link. Finished and not-yet-startable rows are plain text on purpose.
   ========================================================================== */

.task-list { list-style: none; counter-reset: task; }
.task-row {
  counter-increment: task;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  min-height: var(--row-h); padding: 10px 0 10px 14px;
  border-left: 3px solid transparent;
}
.task-row + .task-row { border-top: 1px solid var(--border-subtle); }
.task-row::before {
  content: counter(task);
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  background: var(--surface-sunken); color: var(--text-secondary);
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); font-weight: 700;
}
.task-row.is-next { border-left-color: var(--accent); }
.task-row.is-next::before { background: var(--accent-solid); color: var(--text-on-accent); }

.task-main { flex: 1 1 220px; min-width: 0; }
.task-label { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--text-body); }
a.task-label { color: var(--accent-text); }
a.task-label:hover { text-decoration: underline; }
.task-hint {
  display: block; margin-top: 2px;
  font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.45;
}
.task-state { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.task-note { font-size: var(--fs-xs); color: var(--text-muted); white-space: nowrap; }

.link { color: var(--accent-text); font-weight: 600; }
.link:hover { text-decoration: underline; }

.login-brand .logo { margin: 0 auto; }
.login-note {
  margin-top: 16px; text-align: center;
  font-size: var(--fs-xs); color: var(--text-muted);
}

.error-page { padding: 40px 24px; text-align: center; }
.error-code {
  font-variant-numeric: tabular-nums; font-size: 3.25rem; font-weight: 700;
  line-height: 1; color: var(--accent);
}
.error-page h1 { margin-top: 10px; font-size: var(--fs-xl); font-weight: 600; }
.error-hint { margin-top: 6px; color: var(--text-secondary); font-size: var(--fs-sm); }

/* ==========================================================================
   Department colour on a menu tile.

   THESE ARE CLASSES, NOT AN INLINE `style` ATTRIBUTE. The Content-Security-
   Policy is `style-src 'self'` with no `unsafe-inline`, which blocks the style
   ATTRIBUTE as well as `<style>` blocks. The first version of the home menu
   set `--tile-color` inline; the browser dropped it without a word and every
   tile fell back to the red accent, so treasury and marketing looked like
   general. Nothing in the source was wrong to read - only the rendered page
   showed it. Hence the rule: no inline styles anywhere in this application.
   ========================================================================== */

/*
 * THE FOOT LINE IS TEXT, so it takes a text-grade colour.
 *
 * `.tile-open` ("Uygulamayi ac") paints itself with the department
 * colour. Measured on white: five departments clear the 4.5 text floor,
 * and the brand red does not - 4.44, which is exactly why the palette
 * keeps `--accent-text` apart from `--accent`. `--tile-ink` defaults to
 * the department colour and only general has to override it.
 */
.tile-general    { --tile-color: var(--dept-general); --tile-ink: var(--accent-text); }
.tile-finance    { --tile-color: var(--dept-finance); }
.tile-treasury   { --tile-color: var(--dept-treasury); }
.tile-marketing  { --tile-color: var(--dept-marketing); }
.tile-accounting { --tile-color: var(--dept-accounting); }
/* Hukuk. The token was already in this stylesheet before the department
   existed - the recovered design anticipated it. */
.tile-legal      { --tile-color: var(--dept-legal); }
/* Not finished yet: drawn neutral so "which of these is ready" stays readable
   at a glance. The badge on the tile says which. */
.tile-neutral    { --tile-color: var(--text-icon); }
/* The hub's own pages - Mesajlar, Destek. They belong to no department, and
   they are not unfinished either, so neither the grey nor a department colour
   is true. The hub's own red is. */
.tile-hub        { --tile-color: var(--accent); --tile-ink: var(--accent-text); }

.row-center { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; }
.mt-3 { margin-top: 14px; }

/* ==========================================================================
   Market board - the MKK card grid.

   SELECTION IS A REAL CHECKBOX, styled with :has(). The original marks a
   selected card with a red top bar and defines that bar on EVERY card,
   transparent when unselected - v1 got this wrong once by reading only the
   ".market-card.crypto" rule and skipping the base "border-top: 3px solid"
   line, so 17 of 18 cards showed no feedback at all when clicked.

   No script is involved: the checkbox carries the state, CSS reads it, and
   the form posts it. That is also why "select all" is a link rather than a
   button - a button that needs JS silently does nothing when JS is absent.
   ========================================================================== */

.board { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }

/* THE BOARD'S TOOLBAR: day span left, actions right, ONE surface.
   It lives ABOVE the grid because the grid is the tallest thing in the app -
   measured at 1600px with the 06.09 layout, the download button sat 2707px
   down the page, under everything the person reads to decide what to export.
   The bar is `.period-switch`'s answer to the same fault: loose fields and
   buttons standing on the squared paper read as half-drawn.
   `align-items: end` lines the buttons up with the INPUTS, not the labels. */
.board-tools {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 12px 20px;
  margin-bottom: 6px;
  padding: 14px var(--card-p);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
/* `flex: 1 0 auto` — GROW, NEVER SHRINK. With a shrinkable basis the three
   fields were squeezed until "BİTİŞ" wrapped under the other two and the
   buttons came up beside it: a lopsided two-line block. Refusing to shrink
   moves the WHOLE button row down instead, which is the layout below 1440px.
   The narrower fields are what let all seven controls share one line at
   1600px; the page-wide 210px is more than a `dd/mm/yyyy` box needs. */
.board-tools .filters { flex: 1 0 auto; }
.board-tools .filters .field { min-width: 168px; }
.board-tools .row { flex: 0 0 auto; }

/* THE CALM CARD (15.09). This was the template's market-card verbatim: warm
   frame, a 3px red top on EVERY card and a pink wash. The metric tile it was
   paired with lost the same three with the calm layout; on a board of
   eighteen they read as eighteen pink blocks, and a red line on every card
   says nothing about any of them. Now a plain frame like every card. The
   selection is the filled mark plus a red frame - the one place red means
   something here. The performance board's state strips are its own classes
   (below, "the employee board"). */
.board-card {
  display: flex; flex-direction: column; min-height: 174px;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  transition: transform var(--speed), box-shadow var(--speed), border-color var(--speed);
}
/* The same glow as the home tiles, and for the same reason — these two are
   the app's two hoverable cards and a person moving between them must not
   meet two different answers to the same gesture (§6.0). */
.board-card:hover {
  z-index: 1;
  transform: translateY(-3px);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--accent) 38%, transparent),
    0 0 18px 2px color-mix(in srgb, var(--accent) 20%, transparent),
    var(--shadow-lift);
}
/* THE CHECKBOX IS HIDDEN ONLY WHERE :has() CAN REPLACE IT.
   The selected state is drawn by `:has(> input:checked)` below. In a browser
   without :has() that rule does nothing, and hiding the box unconditionally
   would leave the card with NO way to show or change its selection - a
   feature that silently disappears rather than degrading. Guarded, the plain
   checkbox stays visible there instead: less pretty, still usable. */
@supports selector(:has(*)) {
  .board-card > input {
    position: absolute; width: 1px; height: 1px; opacity: 0;
    margin: 0; pointer-events: none;
  }
}
.board-card:has(> input:checked) { border-color: var(--accent-solid); }
.board-card:has(> input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* THE FOLD (MKK board): its own box and arrow beside the card's label, the
   arrow laid over the header where the original drew it. Folded, the list is
   clipped to its first rows and fades out — the original's rule. */
.board-slot { position: relative; display: flex; min-width: 0; }
.board-slot > .board-card { flex: 1; min-width: 0; }
.board-fold { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.board-fold-space { flex: 0 0 26px; }
.board-body { display: block; }
.board-fold-btn {
  position: absolute; top: 20px; right: 56px; z-index: 2;
  display: grid; place-items: center; width: 26px; height: 26px;
  border: 1px solid var(--border-input); background: var(--surface); color: var(--text-icon);
  cursor: pointer; transition: transform var(--speed), border-color var(--speed), color var(--speed);
}
.board-fold-btn svg { transition: transform var(--speed); }
.board-fold-btn:hover { border-color: var(--accent); color: var(--accent-text); }
.board-slot:hover .board-fold-btn { transform: translateY(-3px); }
.board-slot:has(> .board-fold:focus-visible) .board-fold-btn { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.board-slot:has(> .board-fold:checked) .board-fold-btn svg { transform: rotate(-90deg); }
.board-slot:has(> .board-fold:checked) .board-body {
  max-height: 96px; overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 34%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 34%, transparent 100%);
}

.board-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  min-height: 42px; margin-bottom: 13px;
}
.board-title {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: var(--fs-lg); font-weight: 600;
  /* Muted until selected - the original drops the title to #607083. */
  color: var(--text-muted);
}
.board-card:has(> input:checked) .board-title { color: var(--text-body); }
/* A BOARD CARD THAT IS A LINK HAS NO CHECKBOX, so the rule above could never
   fire and the person's name - the one word the card exists to carry - stayed
   permanently grey. The muted state belongs to the SELECTABLE tile only. */
a.board-card .board-title { color: var(--text-body); }

/* A 24px SQUARE, not a circle: a circle reads as a disabled radio button. */
.board-mark {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none;
  border: 1px solid var(--border-input); border-radius: var(--radius-sm);
  color: transparent;
}
.board-card:has(> input:checked) .board-mark {
  border-color: var(--accent); background: var(--accent-solid); color: var(--text-on-accent);
}

/*
 * THE KEY/VALUE ROW - `specList()` in components.ts.
 *
 * `.board-fields` is the SAME look under an older name and shares these
 * declarations rather than repeating them. It is not renamed because the
 * single-HTML export writes that class by hand (scripts/tek-html), and a
 * class that exists in two generators is a class that drifts in one of
 * them. One rule block, two selectors, one look.
 */
.spec-list > div,
.board-fields > div {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 8px 0; border-top: 1px solid var(--border-subtle);
}
.spec-list > div:first-child,
.board-fields > div:first-child { border-top: 0; }
.spec-list dt,
.board-fields dt { font-size: var(--fs-xs); color: var(--text-muted); min-width: 0; }
/* `white-space: normal` OVERRIDES `.num`'s nowrap HERE, and only here.
   The MKK source puts announcement prose in a value field ("28 Agustos 2026
   haftalik kapanis itibariyla MKK nezdinde kayden saklanan..."), the view
   marks every value `.num`, and nowrap made that one cell 962px wide - which
   pushed the WHOLE PAGE sideways at 1180px, the only horizontal overflow in
   the app. Measured: 1319px against a 1165px viewport.
   A long NUMBER has no spaces, so it still does not break; only prose wraps.
   `min-width: 0` is what lets the flex child shrink at all. */
.spec-list dd,
.board-fields dd {
  font-size: var(--fs-xs); font-weight: 700; text-align: right;
  min-width: 0; white-space: normal;
}

/* ==========================================================================
   Charts (server-rendered SVG)
   ========================================================================== */

.chart { margin: 0; }
.chart + .chart { margin-top: 18px; }
.chart-svg { width: 100%; height: auto; display: block; }
.chart-tick {
  font-variant-numeric: tabular-nums; font-size: 15px; fill: var(--text-muted);
}
/* The column chart's viewBox is narrower, so its text is set smaller to land
   at the same on-screen size as the wide charts'. */
.chart-tick-sm { font-size: 17px; }
/* The quota-fill rows (charts.ts targetBars): text at the page's size, only
   the tracks stretch, so a phone reads them as well as a desktop. */
.target-bars { display: grid; gap: 10px; }
.target-row {
  display: grid; grid-template-columns: 2em minmax(0, 1fr) auto; align-items: center; gap: 12px;
  font-variant-numeric: tabular-nums; font-size: var(--fs-sm); color: var(--text-muted);
}
.target-label { text-align: right; }
.target-track {
  display: block; width: 100%; height: 18px;
  background: var(--surface-sunken); border: 1px solid var(--border);
}
.target-fill { fill: var(--text-body); }
.target-row.is-over .target-fill { fill: var(--accent); }
.target-count { min-width: 5.5em; }
.target-over { grid-column: 2 / -1; color: var(--accent-text); font-family: var(--font-sans); font-size: var(--fs-xs); }
.chart-legend {
  list-style: none; margin: 8px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  font-size: var(--fs-xs); color: var(--text-secondary);
}
.chart-legend li { display: inline-flex; align-items: center; gap: 6px; }
/* The white disc behind a coin logo drawn over its column (columnChart images). */
.chart-logo-ring { fill: var(--surface); stroke: var(--border); stroke-width: 1; }
.chart-key { width: 10px; height: 10px; flex: none; }
/* Charts side by side: two per row, one on a narrow screen. */
.chart-grid { display: grid; gap: var(--rhythm); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 900px) { .chart-grid { grid-template-columns: minmax(0, 1fr); } }
.chart-caption {
  margin-top: 6px; font-size: var(--fs-xs); color: var(--text-muted); font-weight: 700;
}
.chart-empty {
  padding: 28px; text-align: center; color: var(--text-muted);
  background: var(--panel-ground); border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
}

/* ==========================================================================
   Small shared pieces
   ========================================================================== */

.status-meta { display: flex; flex-direction: column; gap: 2px; margin-right: 6px; }
.status-meta strong { font-size: var(--fs-sm); font-weight: 600; }

/*
 * THE ACTION GRID - `actionGrid()` in components.ts.
 *
 * Rows wide enough to aim at, on the module's own landing page. The icon
 * chip repeats the sidebar's icon for the same page, so the eye can carry
 * one mark from here to the rail.
 */
.action-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); }
.action-card {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text-body); text-decoration: none;
  transition: border-color var(--speed), background var(--speed);
}
.action-card:hover { border-color: var(--accent); background: var(--surface-hover); }
.action-icon {
  display: grid; place-items: center; width: 32px; height: 32px; flex: none;
  background: var(--accent-tint); color: var(--accent-text); border-radius: var(--radius-sm);
}
.action-main { display: grid; gap: 2px; min-width: 0; flex: 1; }
.action-main strong { font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
.action-main span { font-size: var(--fs-xs); color: var(--text-muted); }
/* The chevron is a direction, not a second icon: it steps back. */
.action-card > svg:last-child { color: var(--text-icon); flex: none; }

.plain-list { list-style: none; padding-left: 0; }
.plain-list li {
  padding: 8px 0; border-top: 1px solid var(--border-subtle);
  font-size: var(--fs-sm); color: var(--text-secondary);
}
.plain-list li:first-child { border-top: 0; }

/* A filter row: each control needs room for its label, otherwise two adjacent
   labels read as one run-on phrase. */
.filters .field { min-width: 210px; }
/* A SEARCH BOX NEEDS ROOM FOR ITS OWN HINT. At 210px the reconciliation
   result's "Hesap no, ad, tutar ya da açıklama" was cut to "…tutar ya da aç",
   and every other filter bar with a search box had the same width. */
.filters .field:has(input[type="search"]) { min-width: 300px; }

/* ==========================================================================
   Volume: the fetch status strip.

   FIRST ON THE PAGE, above the numbers. The worst failure this module has is a
   list that is QUIETLY SHORT - one exchange missing and the totals read as the
   whole market. An exchange that was never attempted is shown too: silence is
   the state that most needs saying out loud.
   ========================================================================== */

.status-strip { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.status-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: var(--accent-bar) solid var(--text-muted);
  box-shadow: var(--shadow-card);
  padding: 13px 16px;
}
.status-item .label { display: block; margin-bottom: 3px; }
.status-item strong { font-size: var(--fs-sm); font-weight: 600; color: var(--text-secondary); }
.status-item-ok    { border-left-color: var(--ok); }
.status-item-warn  { border-left-color: var(--warn); }
.status-item-error { border-left-color: var(--error); }

.coin { font-variant-numeric: tabular-nums; font-weight: 700; letter-spacing: .01em; }

/* The note input sits INSIDE a table cell, so it must not carry the full
   control height - a 42px control in a 40px row makes every line jump. */
.note-input { height: 30px; font-size: var(--fs-xs); min-width: 140px; }

.card-actions { padding: 12px var(--card-p); border-top: 1px solid var(--border-subtle); }

/* A long list of symbols reads better as flowing text than as a table. */
.coin-list {
  font-variant-numeric: tabular-nums; font-size: var(--fs-xs);
  color: var(--text-secondary); line-height: 1.9; word-break: break-word;
}

/* ==========================================================================
   Feedback: the progress bar, the busy button, the notification.

   ALL THREE DEGRADE. The notification fades on a CSS animation rather than a
   script timer, so it disappears by itself even with app.js blocked; the busy
   button and the progress bar are the only parts that need script, and their
   absence costs polish, not function.
   ========================================================================== */

/* A 3px bar across the very top. Indeterminate on purpose: the server does
   not report progress, and a fake percentage would be a lie that people
   learn to distrust. */
.progress {
  position: fixed; inset-block-start: 0; inset-inline: 0; height: 3px;
  z-index: 200; pointer-events: none;
  background: transparent; overflow: hidden;
}
.progress.is-active::before {
  content: ""; display: block; height: 100%; width: 40%;
  background: var(--accent);
  animation: progress-slide 1s ease-in-out infinite;
}
@keyframes progress-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* The button keeps its width while busy - a label swap that resizes the
   button moves everything next to it. The spinner replaces the icon. */
.btn.is-busy { pointer-events: none; opacity: .85; }
.btn.is-busy .icon { display: none; }
.btn.is-busy::before {
  content: ""; width: 14px; height: 14px; flex: none;
  border: 2px solid currentColor; border-top-color: transparent;
  border-radius: var(--radius-full);
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .progress.is-active::before { animation: none; width: 100%; opacity: .6; }
  .btn.is-busy::before { animation: none; }
}

/* -- notification --------------------------------------------------------- */

/*
 * BOTTOM RIGHT, OUT OF THE WAY. A notice at the top centre sat over the page
 * head and the first row of whatever was just saved - the very thing the
 * reader wanted to look at. In the corner it is seen and covers nothing;
 * several stack upwards, the newest at the bottom.
 */
.toast-region {
  position: fixed; inset-block-end: 20px; inset-inline-end: 20px;
  z-index: 190; display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  width: min(380px, calc(100vw - 32px));
  pointer-events: none;
}

/* A card: surface, a coloured bar on the left, the icon in a tinted round
   well, and at the bottom a hairline that runs down with the time left. */
.toast {
  position: relative; overflow: hidden;
  /* Icon, words and the close button on ONE centre line. Top-aligned, the
     cross sat above the text's middle and looked dropped in by hand. */
  display: flex; align-items: center; gap: 11px;
  width: 100%; padding: 11px 10px 14px 14px;
  background: var(--surface); color: var(--text-body);
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-overlay);
  font-size: var(--fs-sm); font-weight: 600; line-height: 1.45;
  pointer-events: auto;
  --toast-hold: 7s;
  --toast-tone: var(--text-muted);
  --toast-tint: var(--surface-sunken);
  /* In, hold, out. `forwards` leaves it hidden rather than snapping back. */
  animation: toast-in 380ms cubic-bezier(.2, .9, .3, 1.15) both, toast-out 360ms ease-in var(--toast-hold) forwards;
}
.toast > svg {
  flex: none; box-sizing: content-box; width: 16px; height: 16px; padding: 6px;
  border-radius: 50%; background: var(--toast-tint); color: var(--toast-tone);
}
.toast::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--toast-tone); opacity: .45; transform-origin: left;
  animation: toast-timer var(--toast-hold) linear forwards;
}
@keyframes toast-in  { from { opacity: 0; transform: translateX(28px) scale(.96); } }
@keyframes toast-out { to { opacity: 0; transform: translateX(28px); visibility: hidden; } }
@keyframes toast-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Hovering pauses the fade AND the hairline: someone still reading a long
   error must not have it vanish mid-sentence, nor watch a clock run. */
.toast:hover, .toast:focus-within,
.toast:hover::after, .toast:focus-within::after { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  /* No slide, but it STILL leaves on its own - the disappearing is the
     behaviour, the movement is the decoration. */
  .toast { animation: toast-out 1ms ease-in var(--toast-hold) forwards; }
  .toast::after { display: none; }
}
:root[data-motion="off"] .toast::after { display: none; }

.toast-ok    { border-left-color: var(--ok);    --toast-tone: var(--ok);    --toast-tint: var(--ok-tint); }
.toast-error { border-left-color: var(--error); --toast-tone: var(--error); --toast-tint: var(--error-tint); }
.toast-warn  { border-left-color: var(--warn);  --toast-tone: var(--warn);  --toast-tint: var(--warn-tint); }
.toast-info  { border-left-color: var(--info);  --toast-tone: var(--info);  --toast-tint: var(--info-tint); }

.toast-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
/* A square target with the cross in its exact middle. */
.toast-close {
  flex: none; display: grid; place-items: center;
  width: 28px; height: 28px; padding: 0; margin: 0;
  background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer;
  color: var(--text-muted);
  transition: color var(--speed), background var(--speed);
}
.toast-close svg { display: block; }
.toast-close:hover { color: var(--text-body); background: var(--surface-hover); }
.toast-close:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
@media (max-width: 580px) {
  .toast-region { inset-inline: 16px; inset-block-end: 16px; width: auto; align-items: stretch; }
}

/* ==========================================================================
   MKK-language additions: compact hero, status mark, panel chips and steps,
   settings grid, dense board with state-toned top bars.
   ========================================================================== */

/* Text-only hero: the page opener without the surface. */
.page-head-compact {
  background: transparent;
  border-left: 0;
  box-shadow: none;
  padding: 2px 0 0;
}
.page-head-compact h1 { font-size: var(--fs-2xl); }

/* The 42px circle-with-dot state mark from the original status card.
   Colour rides the tone class on the ancestor. */
.status { align-items: center; }
.status-mark {
  display: grid; place-items: center; flex: none;
  width: 42px; height: 42px;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
}
.status-mark::after {
  content: ""; width: 10px; height: 10px;
  border-radius: var(--radius-full);
  background: var(--text-muted);
}
.status-ok .status-mark { background: var(--ok-tint); }
.status-ok .status-mark::after { background: var(--ok); }
.status-warn .status-mark { background: var(--warn-tint); }
.status-warn .status-mark::after { background: var(--warn); }
.status-error .status-mark { background: var(--error-tint); }
.status-error .status-mark::after { background: var(--error); }
.status-busy .status-mark { background: var(--info-tint); }
.status-busy .status-mark::after { background: var(--info); }

/* The right-hand meta block of a status card, left-divided like the original. */
.status-meta {
  border-left: 1px solid var(--border);
  padding-left: 18px;
  margin-left: 6px;
  text-align: right;
}
.status-score { font-variant-numeric: tabular-nums; font-size: var(--fs-xl); font-weight: 700; }

/* The bordered light chip that sits in a panel head ("N kart · M bekliyor"). */
.panel-note {
  display: inline-block;
  border: 1px solid var(--border); background: var(--surface-sunken);
  padding: 6px 10px;
  color: var(--text-muted); font-size: 12px; font-weight: 700;
  white-space: nowrap;
}

/* The circled step number in a panel head — an on-page flow of panels. */
.panel-step {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px;
  border-radius: var(--radius-full);
  background: var(--accent-tint); color: var(--accent-text);
  font-size: 13px; font-weight: 800;
}
.card-head { flex-wrap: nowrap; }
.card-head .panel-step { margin-right: 2px; }

/* One muted sentence inside a flush panel — the original's empty state. */
.panel-empty {
  padding: var(--card-p);
  color: var(--text-muted); font-size: var(--fs-sm);
}
/* …but a padded card body already supplies that inset. Stacked, the two made
   an empty panel twice as tall as it needed to be and pushed the sentence in
   from every edge — the one thing on the page that did not line up. */
.card-body > .panel-empty,
.labelled-group > .panel-empty { padding: 0; }
/* A FLUSH card's body is a `.card-body` too, but has no inset of its own —
   the rule above left its empty sentence on the card's edge (Harf Notu,
   "Uygulanmış harf notları"). There the sentence brings its own. */
.card-body.card-flush > .panel-empty { padding: var(--card-p); }
/* A line of text and a button above a flush card's table (Kullanıcılar,
   unmatched account requests): inset like the card's own head. */
.flush-row { padding: 14px var(--card-p) 0; }

/* The trailing provenance sentence (one per page, at most). */
.footnote { color: var(--text-muted); font-size: var(--fs-xs); line-height: 1.55; }

/* -- the employee board ---------------------------------------------------- */

/* 80 cards want a denser grid than mkk's 18. */
.board-dense { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.board-dense .board-card { min-height: 0; }
a.board-card { color: inherit; }

/* State-toned top bars, and ONLY where the state means something: the red
   strip lights on a card that waits on the viewer, the green one on a
   finished card. Idle and cancelled cards keep the plain frame.
   THE STRIP TAKES ITS 2PX BACK FROM THE PADDING, so the name on a striped
   card sits on the same line as the name on the plain card beside it. */
.board-card-wait { border-top: 3px solid var(--accent); padding-top: 18px; }
.board-card-wait .board-mark {
  border-color: var(--accent); background: var(--accent-solid); color: var(--text-on-accent);
}
.board-card-done { border-top: 3px solid var(--ok); padding-top: 18px; }
.board-card-done .board-mark {
  border-color: var(--ok); background: var(--ok-solid); color: var(--text-on-accent);
}
.board-card-idle .board-title { color: var(--text-muted); }
.board-card-off { opacity: .62; }
.board-card-off .board-title { color: var(--text-muted); }
/* The cardless tail: ONE strip under the board, not one card per person.
   Same frame as a panel so it reads as part of the page, not as a card
   that lost its data. */
.board-cardless {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: var(--rhythm); padding: 14px var(--card-p);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
.board-cardless-title { font-size: var(--fs-sm); font-weight: 600; color: var(--text-body); }

/* The trailing "Şimdi: …" row on a waiting card. */
.board-hint {
  margin-top: 10px; padding-top: 9px;
  border-top: 1px solid var(--border-subtle);
  color: var(--accent-text); font-size: var(--fs-xs); font-weight: 700;
}

/* -- the horizontal approval chain ----------------------------------------- */
.person-chips.chain-strip {
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
}
.chain-strip .person-chip {
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  padding: 12px 14px;
}

/* -- the settings grid ------------------------------------------------------ */

/* File pick as a label-styled button (hidden input inside). */
.file-btn { position: relative; overflow: hidden; cursor: pointer; }
/* The reference file's two jobs, a row each: what it does on the left, its buttons on the right. */
.seed-actions { display: grid; margin-top: 12px; border-top: 1px solid var(--border-subtle); }
.seed-action { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 0; }
.seed-action + .seed-action { border-top: 1px solid var(--border-subtle); }
.seed-action-text { display: grid; gap: 2px; min-width: 0; }
.seed-action form, .seed-upload { display: flex; align-items: center; gap: 8px; flex-shrink: 0; margin: 0; }
.seed-upload .file-btn span { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-btn input[type="file"] {
  position: absolute; inset: 0; opacity: 0; cursor: pointer;
}

/* ==========================================================================
   Status-visualisation vocabulary (queue, phases, legends, context aside)
   ========================================================================== */

/* "Waiting on you" rows — the scannable, one-click form of the red strip. */
.queue { list-style: none; display: grid; gap: 8px; padding: 0; margin: 0; }
.queue-row {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 14px;
  background: var(--surface); border: 1px solid var(--border);
  color: inherit; text-decoration: none;
  transition: transform var(--speed), box-shadow var(--speed), border-color var(--speed);
}
.queue-row:hover {
  transform: translateY(-1px); box-shadow: var(--shadow-card);
  border-color: var(--border-hover);
}
.queue-row .grow { display: grid; gap: 2px; min-width: 0; }
.queue-title { font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
.queue-due { font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); color: var(--text-muted); }

/* THE ROW IS THE LINK; this only looks like a button.
   `.btn` used to be borrowed here, which handed button styling to a <span>
   nothing can focus or press. The look is the same, the promise is not. */
.queue-go {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  flex-shrink: 0; pointer-events: none;
  height: var(--control-h-sm); padding: 0 10px;
  border: 1px solid var(--border-button); background: var(--surface); color: var(--text-body);
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
  transition: background var(--speed), border-color var(--speed);
}
.queue-row:hover .queue-go { background: var(--surface-hover); border-color: var(--border-hover); }

/* Overdue: red kept to its alarm meaning — outlined, not filled. */
.badge-late {
  background: var(--surface-danger); border: 1px solid var(--border-danger); color: var(--accent-text);
}

/* Topbar slot + the waiting counter chip. */
.topbar-slot { display: flex; align-items: center; margin-left: auto; padding-right: 14px; }
.topbar-count {
  display: inline-flex; align-items: center; gap: 8px;
  height: 34px; padding: 0 12px;
  border: 1px solid var(--border-danger); background: var(--surface-danger);
  color: var(--accent-text); text-decoration: none;
  font-size: var(--fs-xs); font-weight: 700;
}
.topbar-count strong {
  font-variant-numeric: tabular-nums; font-size: var(--fs-sm); font-weight: 700;
}
.topbar-count:hover { border-color: var(--accent); transform: translateY(-1px); }
.topbar-count span { white-space: nowrap; }
/* PHONE WIDTH: the chip's words broke onto two lines ("bekleyen / iş") and
   squeezed the page title to "Performans …". There the number stands alone;
   the words stay for screen readers (the .sr-only clipping). */
@media (max-width: 560px) {
  .topbar-slot { padding-right: 0; flex: none; }
  .topbar-count { padding: 0 10px; }
  .topbar-count span {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%);
  }
}

/* The period's calendar as a phase strip; the current phase carries the red
   top line. Replaces the old phase status-card on the board. */
.phase-strip-wrap { display: grid; gap: 6px; }
.phase-strip {
  list-style: none; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px;
}
/*
 * EVERY PHASE HAS ITS TOP EDGE (2026-10-29). The current one's 3px red line
 * was matched by a TRANSPARENT 3px on the others, which kept the heights equal
 * but left them open at the top - three boxes that looked cut off. Now a
 * hairline, and the 2px it saves goes into the padding: same heights.
 */
.phase-strip li {
  display: grid; gap: 2px; align-content: start;
  padding: 12px 12px 10px;
  background: var(--surface); border: 1px solid var(--border);
}
.phase-strip li.is-current {
  border-color: var(--border-warm); border-top: 3px solid var(--accent); padding-top: 10px;
}
.phase-label {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted);
}
.is-current .phase-label { color: var(--text-body); }
.is-past .phase-label svg { color: var(--ok); }
.phase-range { font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); color: var(--text-muted); }
.phase-note { font-size: var(--fs-2xs); font-weight: 700; color: var(--text-secondary); }
/* Kırmızı yalnız gerçekten geciken aşamada: geri sayım ya da kapanmış bir
   pencere bilgidir, alarm değil. */
.phase-note.is-alarm { color: var(--accent-text); }
.phase-hint { font-size: var(--fs-xs); color: var(--text-secondary); }

/* Legend / anchor / coefficient strip — one vocabulary, three jobs. */
.legend-strip {
  list-style: none; display: flex; flex-wrap: wrap; gap: 6px 18px;
  font-size: var(--fs-xs); color: var(--text-secondary);
}
.legend-strip li { display: inline-flex; align-items: baseline; gap: 7px; }
/* THE ANCHORS ARE ONE ROW OR NONE. `auto-fit` with a 150px floor produced
   four columns and left the fifth anchor alone on a second line, which reads
   as a leftover rather than as a scale. Below 900px they stack, where a
   single column is the honest answer. */
.legend-strip-cols {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px 14px;
}
.legend-strip-cols li { align-items: flex-start; }
@media (max-width: 1100px) { .legend-strip-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .legend-strip-cols { grid-template-columns: minmax(0, 1fr); } }
.legend-dot {
  inline-size: 10px; block-size: 10px; flex-shrink: 0; align-self: center;
}
.legend-ok { background: var(--ok); }
.legend-warn { background: var(--warn); }
.legend-error { background: var(--error); }
.legend-info { background: var(--info); }
.legend-accent { background: var(--accent); }
.legend-neutral { background: var(--border); }
.legend-mark {
  display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: 22px; block-size: 22px; padding: 0 4px;
  background: var(--accent-tint); color: var(--accent-text);
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); font-weight: 700;
}

/* Quoted prose: feedback, opinions, notes. The left edge stays GREY — a
   quotation is not an alarm. */
.quote-list { list-style: none; display: grid; gap: 10px; }
.quote {
  padding: 10px 14px;
  background: var(--surface-sunken); border-left: 2px solid var(--border-input);
}
.quote p { font-size: var(--fs-sm); color: var(--text-body); }
.quote-meta {
  margin-top: 6px; display: flex; gap: 10px;
  font-size: var(--fs-2xs); color: var(--text-muted);
}
.quote-meta strong { color: var(--text-secondary); }

/* Native details, framed like everything else. */
/* A CONTAINER INSIDE A CONTAINER CHANGES LAYER. White-on-white with a
   hairline was a box you had to look for; sunken, it reads as a drawer in
   the card - the alternating-layer rule from Carbon's light theme. */
/*
 * "CUKUR" BIR YUZEYIN ICINDE ANLAMLI, SAYFANIN USTUNDE DEGIL.
 *
 * Bu panel her yerde --surface-sunken ile ciziliyordu. Bir kartin icinde
 * dogru: beyazdan bir tik geri cekilmis okunuyor. Ama SAYFANIN uzerinde
 * duran ayni panel zeminle 1.065 — olculdu, ve pratikte ayni renk.
 * Bildirilen hali: "arka plan ile ayni renk, ayirt edilemiyor".
 *
 * Cozum ton degil YER: sayfanin uzerinde bir panel karttir (beyaz, 1.177),
 * bir kartin icinde cukurdur. Tonu koyulastirmak denendi ve olculdu -
 * yeterince ayiran bir gri, uzerindeki soluk yaziyi 3.98'e dusuruyordu,
 * yani bir sorunu otekiyle takas etmek olurdu.
 */
.disclosure { border: 1px solid var(--border); background: var(--panel-ground); }
.disclosure[open] .disclosure-body { background: var(--surface); }
.disclosure summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  min-block-size: 42px; padding: 0 14px;
  font-size: var(--fs-sm); font-weight: 700; color: var(--text-body);
  cursor: pointer; list-style: none;
}
.disclosure summary::-webkit-details-marker { display: none; }
.disclosure summary svg { color: var(--text-icon); transition: transform var(--speed); }
.disclosure[open] summary { border-bottom: 1px solid var(--border-subtle); }
.disclosure[open] summary svg { transform: rotate(180deg); }
.disclosure-body { padding: 14px; }

/* The judging surface: work in the main column, context beside it. */
.card-split {
  display: grid; grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--rhythm); align-items: start;
}
.card-split-main { display: grid; gap: var(--rhythm); min-width: 0; }
.context-aside {
  display: grid; gap: 14px; align-content: start;
  padding: var(--card-p);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
.labelled-group { display: grid; gap: 6px; }
.labelled-group + .labelled-group { border-top: 1px solid var(--border-subtle); padding-top: 12px; }

/* The goal row's check-in state; sized for the fixed-layout goal grid. */
.progress-tick { display: inline-block; vertical-align: middle; line-height: 0; }
.goal-grid .progress-tick { margin-top: 4px; }

/* Calibration: the corrected letter's past, struck through beside it. */

/* The stacked period bar stretches full width. */
.chart-stacked .chart-svg { width: 100%; height: 18px; display: block; }

/* The print button means nothing without script — hidden when script is off;
   the page still prints cleanly via the browser menu. */
html:not(.js) [data-print] { display: none; }

/* A control that only means something with script - a live filter, a bulk
   tick - is hidden without it, rather than drawn and inert. */
html:not(.js) [data-needs-script] { display: none; }

/* Content that exists FOR the printed page only (print hides every form, so
   a form-only card carries a read-only stand-in for paper). */
.print-only { display: none; }

/* ==========================================================================
   Tones: named colours for a thing's own identity (an asset of the weekly
   report), as CLASSES — the CSP drops a style attribute, so a colour cannot
   ride in on the markup. The fourteen are the report editor's
   own asset colours and palette. They mark rules, bars, dots and round
   marks — never running text, which stays on the text tokens.
   ========================================================================== */
:root {
  --tone-red: #dc0005;     --tone-blue: #1f5fd0;   --tone-green: #0f7a45;
  --tone-amber: #b7791f;   --tone-purple: #6b3fa0; --tone-teal: #0e7c86;
  --tone-rose: #b5384f;    --tone-slate: #4a5568;  --tone-orange: #f7931a;
  --tone-indigo: #627eea;  --tone-gold: #d4af37;   --tone-mint: #14f195;
  --tone-crimson: #e84142; --tone-ink: #23292f;
  /* The marker-pen highlight of the report's "vurgu" emphasis. */
  --mark-bg: #fff3a3;
}
@supports (color: light-dark(#000000, #ffffff)) {
  :root {
    --tone-red: light-dark(#dc0005, #f0514b);
    --tone-blue: light-dark(#1f5fd0, #6b9cf5);
    --tone-green: light-dark(#0f7a45, #3fb27a);
    --tone-amber: light-dark(#b7791f, #e0a64a);
    --tone-purple: light-dark(#6b3fa0, #a78bdb);
    --tone-teal: light-dark(#0e7c86, #3fb5bf);
    --tone-rose: light-dark(#b5384f, #e0708a);
    --tone-slate: light-dark(#4a5568, #a0aec0);
    --tone-orange: light-dark(#f7931a, #f7931a);
    --tone-indigo: light-dark(#627eea, #8ea2f2);
    --tone-gold: light-dark(#d4af37, #d4af37);
    --tone-mint: light-dark(#14f195, #14f195);
    --tone-crimson: light-dark(#e84142, #f06b6c);
    --tone-ink: light-dark(#23292f, #c9d1d9);
    --mark-bg: light-dark(#fff3a3, #5c4d00);
  }
}
/*
 * THE LETTERS ON A ROUND MARK ARE READ AGAINST THE TONE AS IT IS DRAWN. Every
 * tone is lightened for the dark palette (it also draws rules and bars on a
 * dark surface) while the initials on it stayed white: white on the dark
 * palette's slate measured 2,3:1 on the organisation chart, and three of the
 * light tones (amber, indigo, crimson) were under 4,5:1 with white as well.
 * Ink where the tone is light, white where it is dark - in both palettes.
 */
.tone-red     { --tone: var(--tone-red);     --tone-on: #ffffff; }
.tone-blue    { --tone: var(--tone-blue);    --tone-on: #ffffff; }
.tone-green   { --tone: var(--tone-green);   --tone-on: #ffffff; }
.tone-amber   { --tone: var(--tone-amber);   --tone-on: #111418; }
.tone-purple  { --tone: var(--tone-purple);  --tone-on: #ffffff; }
.tone-teal    { --tone: var(--tone-teal);    --tone-on: #ffffff; }
.tone-rose    { --tone: var(--tone-rose);    --tone-on: #ffffff; }
.tone-slate   { --tone: var(--tone-slate);   --tone-on: #ffffff; }
.tone-orange  { --tone: var(--tone-orange);  --tone-on: #111418; }
.tone-indigo  { --tone: var(--tone-indigo);  --tone-on: #111418; }
.tone-gold    { --tone: var(--tone-gold);    --tone-on: #111418; }
.tone-mint    { --tone: var(--tone-mint);    --tone-on: #111418; }
.tone-crimson { --tone: var(--tone-crimson); --tone-on: #111418; }
.tone-ink     { --tone: var(--tone-ink);     --tone-on: #ffffff; }
@supports (color: light-dark(#000000, #ffffff)) {
  .tone-red, .tone-blue, .tone-green, .tone-purple,
  .tone-teal, .tone-rose, .tone-slate, .tone-ink { --tone-on: light-dark(#ffffff, #111418); }
}

/* ==========================================================================
   A published document (components.ts "A PUBLISHED DOCUMENT'S PIECES") —
   the weekly market report's look, from the original report editor's own
   stylesheet: square corners, a 3px rule on the left for a band's identity,
   small uppercase labels, big tabular figures, reading text at 70ch.
   ========================================================================== */
.monogram {
  position: relative; flex: none; display: inline-grid; place-items: center;
  border-radius: var(--radius-full); overflow: hidden;
  background: var(--tone, var(--accent)); color: var(--tone-on, #ffffff);
  font-weight: 700; line-height: 1; letter-spacing: .02em;
}
.monogram-sm { width: 28px; height: 28px; font-size: var(--fs-2xs); }
.monogram-md { width: 34px; height: 34px; font-size: var(--fs-sm); }
.monogram-lg { width: 44px; height: 44px; font-size: var(--fs-lg); }
.monogram-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: var(--surface); }

.em-up { color: var(--ok-text); font-weight: 600; }
.em-down { color: var(--error-text); font-weight: 600; }
.em-info { color: var(--info-text); }
.em-warn { color: var(--warn-text); }
.em-muted { color: var(--text-muted); }
.em-mark { background: var(--mark-bg); color: var(--text-body); padding: 0 .18em; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.trend-up { color: var(--ok-text); }
.trend-down { color: var(--error-text); }
.trend-mark { font-size: .75em; vertical-align: .1em; }

.key-points {
  margin: 0 0 24px; padding: var(--card-p);
  background: var(--surface-sunken); border: 1px solid var(--border); border-left: 3px solid var(--accent);
}
.key-points-title {
  margin: 0 0 12px; font-size: var(--fs-xs); font-weight: 700; color: var(--accent-text);
}
.key-points ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.key-points li {
  position: relative; padding-left: 22px;
  font-size: 1.0625rem; font-weight: 500; line-height: 1.4; color: var(--text-body);
}
.key-points li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--accent);
}

.stat-band {
  margin: 0 0 16px; padding: 20px var(--card-p);
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--tone, var(--accent));
}
.stat-band-positive { background: var(--ok-tint); border-left-color: var(--ok); }
.stat-band-label {
  margin: 0 0 16px; font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted);
}
.stat-band-positive .stat-band-label { color: var(--ok-text); }
.stat-band-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 18px; }
.stat-band-cell { display: grid; align-content: start; gap: 5px; padding-right: 18px; border-right: 1px solid var(--border); }
.stat-band-cell:last-child { border-right: 0; padding-right: 0; }
.stat-band-positive .stat-band-cell { border-right-color: transparent; }
.stat-band-cell-label { font-size: var(--fs-sm); color: var(--text-secondary); }
.stat-band-positive .stat-band-cell-label { color: var(--ok-text); font-weight: 600; }
.stat-band-value {
  font-size: 1.875rem; font-weight: 700; line-height: 1.2; letter-spacing: -.03em;
  color: var(--text-body); font-variant-numeric: tabular-nums;
}
.stat-band-positive .stat-band-value { color: var(--ok-text); }
.stat-band-value.trend-up { color: var(--ok-text); }
.stat-band-value.trend-down { color: var(--error-text); }
.stat-band-sub { font-size: var(--fs-sm); color: var(--text-secondary); }
.stat-band-positive .stat-band-sub { color: var(--ok-text); }
.stat-band-foot { font-size: var(--fs-xs); color: var(--text-muted); }
.stat-band-positive .stat-band-foot { color: var(--ok-text); }

.figure-card { margin: 0 0 16px; padding: 20px var(--card-p); background: var(--surface); border: 1px solid var(--border); }
.figure-card-title { margin: 0 0 8px; font-size: var(--fs-lg); font-weight: 700; line-height: 1.35; color: var(--text-body); }
.figure-card-lead { margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); line-height: 1.6; }
.figure-card-body { margin-top: 12px; }
.figure-card-body .chart { margin: 0; }
.figure-card-mid .picture { max-width: 580px; }
.figure-card-source {
  margin-top: 12px; padding-top: 8px; border-top: 1px solid var(--border);
  font-size: var(--fs-xs); color: var(--text-muted);
}
.figure-note { margin-top: 16px; padding-left: 16px; border-left: 2px solid var(--border-input); max-width: 70ch; }
.figure-note-label {
  margin: 0 0 8px; font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted);
}

.rich-text { max-width: 70ch; margin: 0 0 16px; color: var(--text-body); }
.rich-text h3 { margin: 0 0 12px; font-size: var(--fs-lg); font-weight: 700; }
.rich-text p { margin: 0; font-size: var(--fs-md); line-height: 1.6; }
.rich-text p + p, .rich-text ul + p, .rich-text p + ul { margin-top: 14px; }
.rich-text ul { margin: 0; padding-left: 22px; display: grid; gap: 8px; }
.rich-text li { font-size: var(--fs-md); line-height: 1.6; }
.rich-text-compact { margin: 0; }
.rich-text-compact p, .rich-text-compact li { font-size: var(--fs-sm); }
.callout .rich-text { max-width: none; }

.tagged-list { display: grid; gap: 9px; margin: 0 0 12px; }
.tagged-item {
  display: grid; grid-template-columns: 118px minmax(0, 1fr);
  border: 1px solid var(--tagged-edge, var(--border)); color: inherit; text-decoration: none;
  transition: box-shadow .15s, transform .15s;
}
a.tagged-item:hover { box-shadow: var(--shadow-card), 0 4px 16px rgba(20, 20, 20, .10); transform: translateY(-1px); }
.tagged-badge { display: flex; align-items: center; justify-content: center; padding: 14px 10px; text-align: center; background: var(--tagged-tint, var(--surface-sunken)); }
.tagged-tag { padding: 4px 10px; font-size: var(--fs-xs); font-weight: 700; line-height: 1.2; color: var(--tagged-text, var(--text-body)); background: var(--surface); border: 1px solid var(--tagged-edge, var(--border)); }
.tagged-body { display: grid; align-content: center; gap: 7px; padding: 14px 18px; background: var(--surface); border-left: 1px solid var(--border-subtle); }
.tagged-title { font-size: var(--fs-lg); font-weight: 600; line-height: 1.35; color: var(--text-body); }
.tagged-text { font-size: var(--fs-md); line-height: 1.55; color: var(--text-secondary); }
.tagged-info  { --tagged-tint: var(--info-tint);  --tagged-text: var(--info-text);  --tagged-edge: var(--info); }
.tagged-ok    { --tagged-tint: var(--ok-tint);    --tagged-text: var(--ok-text);    --tagged-edge: var(--ok); }
.tagged-warn  { --tagged-tint: var(--warn-tint);  --tagged-text: var(--warn-text);  --tagged-edge: var(--warn); }
.tagged-error { --tagged-tint: var(--error-tint); --tagged-text: var(--error-text); --tagged-edge: var(--error); }

.outcome-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0 0 12px; }
.outcome { padding: 20px var(--card-p); border: 1px solid var(--outcome-edge); border-left: 3px solid var(--outcome-edge); background: var(--outcome-tint); }
.outcome-ok    { --outcome-tint: var(--ok-tint);    --outcome-edge: var(--ok);    --outcome-text: var(--ok-text); }
.outcome-error { --outcome-tint: var(--error-tint); --outcome-edge: var(--error); --outcome-text: var(--error-text); }
.outcome-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 14px; }
.outcome-badge { padding: 3px 11px; font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em; color: var(--outcome-text); background: var(--surface); border: 1px solid var(--outcome-edge); }
.outcome-title { font-size: 1.3125rem; font-weight: 700; line-height: 1.2; color: var(--outcome-text); }
.outcome ul { margin: 0; padding-left: 20px; display: grid; gap: 8px; }
.outcome li { font-size: var(--fs-md); line-height: 1.55; color: var(--text-body); }
.outcome li.outcome-empty { color: var(--text-muted); list-style: none; margin-left: -20px; }
.outcome-target { margin: 16px 0 0; padding-top: 12px; border-top: 1px solid var(--border); font-size: 1.125rem; font-weight: 700; color: var(--outcome-text); }
.outcome-note { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--text-secondary); }

.agenda { display: grid; margin: 0 0 16px; border-top: 1px solid var(--border); }
.agenda-item { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 16px; padding: 16px 0; border-bottom: 1px solid var(--border); }
.agenda-when { display: flex; flex-direction: column; gap: 2px; text-align: right; }
.agenda-day { font-size: 1.625rem; font-weight: 700; line-height: 1; color: var(--text-body); font-variant-numeric: tabular-nums; }
.agenda-month { font-size: var(--fs-xs); color: var(--text-secondary); }
.agenda-time { margin-top: 2px; font-size: var(--fs-xs); color: var(--text-muted); }
.agenda-title { margin: 0; font-size: var(--fs-lg); font-weight: 700; line-height: 1.35; color: var(--text-body); }
.agenda-text { margin: 4px 0 0; max-width: 70ch; font-size: var(--fs-sm); color: var(--text-secondary); }
.agenda-outcomes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 12px; }
.agenda-outcome-label { position: relative; margin: 0; padding-left: 14px; font-size: var(--fs-xs); font-weight: 700; letter-spacing: .03em; color: var(--agenda-text); }
.agenda-outcome-label::before { content: ""; position: absolute; left: 0; top: .42em; width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--agenda-dot); }
.agenda-ok    { --agenda-dot: var(--ok);    --agenda-text: var(--ok-text); }
.agenda-error { --agenda-dot: var(--error); --agenda-text: var(--error-text); }
.agenda-main-mark { margin-left: 8px; font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0; text-transform: lowercase; color: var(--text-muted); }
.agenda-outcome-body { margin: 4px 0 0; font-size: var(--fs-sm); line-height: 1.55; color: var(--text-body); }
.agenda-outcome-result { margin: 4px 0 0; font-size: var(--fs-sm); font-weight: 700; color: var(--agenda-text); }

.link-card { display: flex; align-items: center; gap: 14px; margin: 0 0 12px; padding: 14px 18px; background: var(--surface); border: 1px solid var(--border); }
.link-card-icon { display: grid; place-items: center; width: 40px; height: 40px; flex: none; color: var(--accent-text); background: var(--accent-tint); }
.link-card-title { margin: 0; font-size: 1.0625rem; font-weight: 600; color: var(--text-body); }
.link-card-host { font-size: var(--fs-sm); color: var(--text-muted); }

.picture { display: block; max-width: 100%; width: auto; height: auto; margin: 0 auto; border: 1px solid var(--border); }
.picture-sample {
  display: grid; place-items: center; min-height: 220px;
  background:
    repeating-linear-gradient(135deg, transparent 0 24px, var(--accent-tint) 24px 34px),
    var(--surface-sunken);
  border: 1px dashed var(--border-input);
  color: var(--text-muted); font-weight: 600;
}
.figure { margin: 0 0 14px; }
.figure .picture { width: 100%; }
.figure-mid .picture { max-width: 580px; }
.figure figcaption { margin-top: 10px; font-size: var(--fs-sm); line-height: 1.55; color: var(--text-secondary); }

.placeholder-note { padding: 20px var(--card-p); background: var(--accent-tint); border: 1px dashed var(--border-warm); }
.placeholder-note-label { margin: 0 0 10px; font-size: var(--fs-xs); font-weight: 700; color: var(--accent-text); }
.placeholder-note-line { margin: 0; font-size: var(--fs-md); line-height: 1.55; color: var(--accent-text); }
.placeholder-note-line + .placeholder-note-line { margin-top: 6px; }

.doc-heading { margin: 48px 0 16px; font-size: 1.3125rem; font-weight: 700; line-height: 1.22; letter-spacing: -.02em; color: var(--text-body); scroll-margin-top: 88px; }
.doc-heading::before { content: ""; display: block; width: 32px; height: 3px; margin-bottom: 12px; background: var(--accent); }
.doc-part { display: block; }
.part-heading {
  display: flex; align-items: center; gap: 12px; margin: 64px 0 24px; padding-top: 24px;
  border-top: 3px solid var(--tone, var(--accent));
  font-size: 1.3125rem; font-weight: 700; line-height: 1.22; letter-spacing: -.02em; color: var(--text-body);
  scroll-margin-top: 88px;
}
.doc-part:first-child .part-heading { margin-top: 8px; }
.part-heading-tag { padding: 2px 10px; font-size: var(--fs-xs); font-weight: 700; letter-spacing: .09em; color: var(--text-muted); border: 1px solid var(--border); }

.rail-layout { display: grid; grid-template-columns: 224px minmax(0, 1fr); gap: 48px; align-items: start; margin-top: var(--rhythm); }
.rail-layout-single { grid-template-columns: minmax(0, 1fr); }
.rail-main { min-width: 0; max-width: 840px; }
.contents-rail { position: sticky; top: 88px; max-height: calc(100vh - 104px); overflow: auto; overscroll-behavior: contain; padding-top: 8px; }
.contents-title { margin: 0 0 12px; font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted); }
.contents-list { list-style: none; margin: 0; padding: 0; border-left: 2px solid var(--border); }
.contents-item a {
  display: block; margin-left: -2px; padding: 8px 12px; border-left: 2px solid transparent;
  font-size: var(--fs-base); line-height: 1.35; color: var(--text-secondary); text-decoration: none;
}
.contents-item a:hover { color: var(--text-body); }
.contents-item a.is-active { border-left-color: var(--accent); color: var(--accent-text); font-weight: 600; }
.contents-level-1 a { padding-top: 12px; font-size: var(--fs-md); font-weight: 700; color: var(--text-body); }
.contents-level-2 a { padding-left: 24px; }
.contents-top {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 16px; padding: 6px 12px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-secondary); text-decoration: none;
  border: 1px solid var(--border);
}
.contents-top:hover { border-color: var(--accent); color: var(--accent-text); }
@media (max-width: 1080px) {
  .rail-layout { display: block; }
  .contents-rail { position: static; max-height: none; margin-bottom: var(--rhythm); padding: 16px; background: var(--surface); border: 1px solid var(--border); }
  .contents-list { display: flex; flex-wrap: wrap; gap: 4px 8px; border-left: 0; }
  .contents-item a, .contents-level-2 a { margin: 0; padding: 4px 8px; border-left: 0; }
  .contents-item a.is-active { background: var(--accent-tint); }
  .contents-top { display: none; }
}

.back-to-top {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: var(--radius-full);
  background: var(--surface); color: var(--text-body); border: 1px solid var(--border-input);
  box-shadow: 0 4px 16px rgba(20, 20, 20, .14);
}
.back-to-top[hidden] { display: none; }
.back-to-top:hover { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--text-on-accent); }

.fact-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin: 0; padding: 16px var(--card-p) 20px; background: var(--surface); border: 1px solid var(--border); }
.fact dt { font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted); }
.fact dd { margin: 6px 0 0; font-size: 1.125rem; font-weight: 600; color: var(--text-body); }
.fact-person { display: inline-flex; align-items: center; gap: 9px; }

.colophon { margin-top: 48px; padding-top: 16px; border-top: 1px solid var(--border); }
.colophon p { margin: 0; font-size: var(--fs-sm); line-height: 1.6; color: var(--text-muted); }
.colophon p + p { margin-top: 6px; }

@media (max-width: 760px) {
  .fact-row, .outcome-pair, .agenda-outcomes { grid-template-columns: minmax(0, 1fr); }
  .tagged-item { grid-template-columns: minmax(0, 1fr); }
  .tagged-badge { justify-content: flex-start; padding: 11px 16px 0; }
  .tagged-body { border-left: 0; padding-top: 9px; }
  .agenda-item { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .agenda-when { flex-direction: row; align-items: baseline; gap: 8px; text-align: left; }
  .stat-band-cell { border-right: 0; padding-right: 0; }
}

/* Paper: the rail, the button and every control go; the bands keep their colour. */
@media print {
  .contents-rail, .back-to-top, .picker-tabs, .report-toolbar { display: none !important; }
  .rail-layout { display: block; }
  .rail-main { max-width: none; }
  .key-points, .stat-band, .figure-card, .outcome, .agenda-item, .tagged-item, .rich-text, .link-card {
    break-inside: avoid; -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  .doc-heading, .part-heading { break-after: avoid; }
  .rail-main a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 8pt; color: var(--text-muted); word-break: break-all; font-weight: 400; }
}

/* The report saved as one file: no shell around it. */
body.standalone { margin: 0; background: var(--surface-page); color: var(--text-body); font-family: var(--font-sans); }
.standalone-main { max-width: 1200px; margin: 0 auto; padding: 24px; }

/* ==========================================================================
   Editing a document part by part (components.ts) and the pieces of its
   forms — the report editor's block card, order panel, asset tiles.
   ========================================================================== */
.edit-frame { background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-card); scroll-margin-top: 88px; }
.edit-frame.is-open { border-color: var(--border-input); border-left: 3px solid var(--accent); }
.edit-frame-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 6px 12px; border-bottom: 1px solid var(--border-subtle); background: var(--surface-sunken); }
.edit-frame-no {
  display: grid; place-items: center; min-width: 24px; height: 24px; padding: 0 6px;
  font-size: var(--fs-xs); font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-on-accent); background: var(--text-secondary);
}
.edit-frame.is-open .edit-frame-no { background: var(--accent-solid); }
.edit-frame-title { font-size: var(--fs-xs); font-weight: 700; color: var(--text-secondary); }
.edit-frame-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.edit-frame-actions form { display: contents; }
.edit-frame-body { padding: 18px var(--card-p); }
.edit-frame-body > :last-child { margin-bottom: 0; }
.edit-frame-body[data-area-href] { cursor: pointer; }
html.js .edit-frame-body[data-area-href]:hover { background: var(--surface-hover); }
.edit-frame.is-muted .edit-frame-body { padding: 12px; }
.edit-frame.is-open .edit-frame-body { display: grid; gap: 16px; }

.action-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.action-row { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 6px 6px 6px 8px; border: 1px solid var(--border-subtle); background: var(--surface); }
.action-row[hidden] { display: none; }
.action-row:hover { border-color: var(--border-input); }
.action-row-icon { display: grid; place-items: center; flex: none; width: 24px; color: var(--text-icon); }
.action-row-text { display: grid; flex: 1 1 auto; min-width: 0; }
.action-row-text strong { font-size: var(--fs-sm); font-weight: 600; color: var(--text-body); }
.action-row-text span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: var(--fs-xs); color: var(--text-muted); }
.action-row .btn { flex: none; }
.context-aside > *, .report-panel > *, .order-row { min-width: 0; }

.check-field { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; font-size: var(--fs-base); color: var(--text-body); }
.check-field .checkbox { margin-top: 2px; flex: none; }
.check-field small { display: block; margin-top: 2px; }

.row-list { display: grid; gap: 8px; }
.row-list > .field-hint { margin: 0; }
.row-list-item { display: flex; align-items: flex-start; gap: 8px; padding: 10px; background: var(--surface-sunken); border: 1px solid var(--border-subtle); }
.row-list-fields { flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
.row-list-wide .row-list-fields { grid-template-columns: minmax(0, 1fr); }
.row-list-remove { flex: none; }
.row-list-add { padding-top: 2px; }

.form-columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.form-column { display: grid; gap: 12px; min-width: 0; margin: 0; padding: 16px; border: 1px solid var(--border); border-top: 3px solid var(--border-input); background: var(--surface); }
.form-column-ok { border-top-color: var(--ok); }
.form-column-error { border-top-color: var(--error); }
.form-column-info { border-top-color: var(--info); }
.form-column-warn { border-top-color: var(--warn); }
.form-column-title { padding: 0 6px; font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
.form-column-ok .form-column-title { color: var(--ok-text); }
.form-column-error .form-column-title { color: var(--error-text); }
@media (max-width: 900px) { .form-columns { grid-template-columns: minmax(0, 1fr); } }

.computed-line { margin: 0; padding: 10px 14px; font-size: var(--fs-sm); color: var(--text-secondary); background: var(--surface-sunken); border: 1px solid var(--border-subtle); }
.computed-line.trend-up { color: var(--ok-text); }
.computed-line.trend-down { color: var(--error-text); }

.order-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.order-row { display: flex; align-items: center; gap: 8px; min-height: 38px; padding: 2px 4px 2px 6px; border: 1px solid transparent; }
.order-row:hover, .order-row:focus-within { background: var(--surface-hover); border-color: var(--border-subtle); }
.order-row.is-active { border-color: var(--accent); }
.order-no { min-width: 20px; font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted); font-variant-numeric: tabular-nums; text-align: right; }
.order-icon { display: grid; place-items: center; color: var(--text-icon); }
.order-name { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: var(--fs-base); color: var(--text-body); text-decoration: none; }
.order-name:hover { color: var(--accent-text); text-decoration: underline; }
.order-row.is-muted .order-name { color: var(--text-muted); font-style: italic; }
.order-badge { padding: 1px 6px; font-size: var(--fs-2xs); font-weight: 700; color: var(--info-text); background: var(--info-tint); border: 1px solid var(--info); }
.order-tools { display: flex; align-items: center; gap: 0; }
.order-step { display: inline-flex; }
.order-step .btn[disabled] { visibility: hidden; }

.picker-tabs { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }
.picker-tab { position: relative; display: flex; min-width: 190px; background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--tone, var(--border-input)); box-shadow: var(--shadow-card); }
.picker-tab.is-active { background: var(--surface-selected); border-color: var(--tone, var(--accent)); }
.picker-tab-link { display: flex; align-items: center; gap: 12px; flex: 1 1 auto; padding: 12px 36px 12px 14px; color: inherit; text-decoration: none; }
.picker-tab-text { display: grid; gap: 1px; }
.picker-tab-text strong { font-size: var(--fs-md); color: var(--text-body); }
.picker-tab-text span { font-size: var(--fs-sm); color: var(--text-secondary); }
.picker-tab-meta { color: var(--text-body) !important; font-weight: 600; }
.picker-tab-tool { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; width: 26px; height: 26px; color: var(--text-icon); }
.picker-tab-tool:hover { color: var(--accent-text); background: var(--surface-hover); }
.picker-tab-add { display: inline-flex; align-items: center; gap: 6px; padding: 12px 16px; border: 1px dashed var(--border-input); color: var(--accent-text); text-decoration: none; font-weight: 600; font-size: var(--fs-base); }
.picker-tab-add:hover { border-color: var(--accent); background: var(--accent-tint); }

.usage-meter { display: inline-flex; align-items: center; padding: 4px 10px; font-size: var(--fs-xs); font-weight: 600; color: var(--text-secondary); border: 1px solid var(--border); background: var(--surface); }
.usage-warn { color: var(--warn-text); background: var(--warn-tint); border-color: var(--warn); }
.usage-crit { color: var(--error-text); background: var(--error-tint); border-color: var(--error); }

.markup-toolbar { position: fixed; z-index: 450; display: flex; gap: 2px; padding: 4px; background: var(--surface); border: 1px solid var(--border-input); box-shadow: 0 4px 16px rgba(20, 20, 20, .16); }
.markup-toolbar[hidden] { display: none; }
.markup-btn { display: grid; place-items: center; width: 28px; height: 28px; border: 0; background: transparent; color: var(--text-body); cursor: pointer; }
.markup-btn:hover, .markup-btn:focus-visible { background: var(--surface-hover); }
.markup-swatch { width: 14px; height: 14px; border: 1px solid var(--border-input); }
.markup-up .markup-swatch { background: var(--ok); }
.markup-down .markup-swatch { background: var(--error); }
.markup-info .markup-swatch { background: var(--info); }
.markup-warn .markup-swatch { background: var(--warn); }
.markup-muted .markup-swatch { background: var(--text-muted); }
.markup-mark .markup-swatch { background: var(--mark-bg); }

.file-drop.has-preview { align-items: center; }
.file-drop-preview { width: 64px; height: 64px; flex: none; object-fit: contain; background: var(--surface-sunken); border: 1px solid var(--border); }

.context-aside.is-sticky { position: sticky; top: 84px; max-height: calc(100vh - 100px); overflow: auto; overscroll-behavior: contain; min-width: 0; }
@media (max-width: 1100px) { .context-aside.is-sticky { position: static; max-height: none; overflow: visible; } }
/* withAside PROMISED "below 1100px the aside drops underneath — never a
   horizontal scrollbar" and no rule did it: at 390px the main column was
   squeezed beside a 340px aside. This is that rule. */
@media (max-width: 1100px) { .card-split { grid-template-columns: minmax(0, 1fr); } }

/* -- the weekly report's own screens ---------------------------------------- */
.report-toolbar { gap: 8px; }
.report-toolbar > form { display: flex; align-items: flex-end; gap: 6px; }
.report-toolbar .field { min-width: 220px; }
.report-blocks { display: grid; gap: 16px; }
.report-blocks > *, .edit-frame-body > * { min-width: 0; }
.edit-frame-body { overflow-wrap: anywhere; }
.report-blocks > .doc-heading { margin: 16px 0 -6px; }
.report-block-form { display: block; }
.report-form-actions { margin-top: 2px; padding-top: 14px; border-top: 1px solid var(--border-subtle); }
.report-save-all { margin-top: 16px; }
.report-panel { display: grid; gap: 10px; }
.report-panel + .report-panel { margin-top: 12px; padding-top: 16px; border-top: 1px solid var(--border); }
.report-panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.report-panel-head .card-title { margin: 0; }
.catalog-form { display: grid; gap: 8px; }
/* A select is as wide as its longest option ("12. bölümden sonra — …"); in a side panel it must not be. */
.catalog-form .field, .catalog-form select.control { min-width: 0; max-width: 100%; }
.catalog-form .kv-group { margin: 8px 0 2px; }
.pick-tile-icon { display: grid; place-items: center; width: 28px; color: var(--text-icon); }
.gate-list { margin: 6px 0 12px; padding: 10px 12px; background: var(--surface-sunken); border-left: 3px solid var(--border-input); font-size: var(--fs-sm); }
.gate-list-warn { border-left-color: var(--warn); }

/* ==========================================================================
   Print: the karne (and any page) as a clean A4 document
   ========================================================================== */
@media print {
  @page { size: A4; margin: 14mm; }
  body { background: #fff; }
  .sidebar, .topbar, .btn, form, .filters, .toast-region, .progress,
  .page-head .row, .footnote, .queue, .phase-strip-wrap,
  .disclosure, [data-print] { display: none !important; }
  .shell { display: block; }
  .main-col { background: none; }
  .main { max-width: none; padding: 0; }
  .card, .status, .quote, .section, .metric { break-inside: avoid; box-shadow: none; }
  .board-card, .queue-row { box-shadow: none; }
  a { color: inherit; text-decoration: none; }
  .print-only { display: block; }
}

/* ==========================================================================
   Performance module

   One main screen (the Pano board of employee cards), a single-column card
   workspace, a status-card result on the karne. Composed from the shared
   MKK-language vocabulary above; only the leftovers live here.
   ========================================================================== */

/* Team work stays a compact filterable list; there is no separate picker wall. */
.perf-team-filters {
  display: grid; grid-template-columns: minmax(220px, 1.5fr) minmax(160px, .8fr) minmax(150px, .7fr) auto;
  align-items: end; gap: 10px;
}
.perf-filter-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
/* The journal's search and its four filters in one row, the reset at its end. */
.journal-filters { grid-template-columns: minmax(200px, 1.4fr) repeat(4, minmax(140px, 1fr)) auto; }
@media (max-width: 1280px) { .journal-filters { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); } }

.perf-form-intro { padding-bottom: 12px; }
.perf-form-intro .alert { margin: 0; }

/* Person first: no card work starts until the user has deliberately chosen
   whose review they are handling. */
.perf-person-picker {
  display: grid; grid-template-columns: minmax(180px, .65fr) minmax(280px, 1fr) auto;
  align-items: end; gap: 10px;
}
.perf-assignment-grid {
  display: grid; grid-template-columns: minmax(260px, .75fr) minmax(0, 2fr);
  gap: 14px; margin-top: 14px;
}
.perf-assignment-grid > section {
  min-width: 0; padding: 16px; background: var(--surface-sunken);
  border-radius: var(--radius-sm);
}
.perf-assignment-grid h3 { font-size: var(--fs-md); }
.perf-assignment-grid h3 + p {
  margin: 5px 0 14px; color: var(--text-muted); font-size: var(--fs-xs); line-height: 1.45;
}
.perf-assignment-grid form > * + * { margin-top: 12px; }

/* A source changes the one TITLE CELL, never the shape of the row. With
   script, exactly one of the three controls shows; without script both
   controls render stacked with their small labels visible - the server
   resolves by the type select either way. */
.js [data-goal-catalogue], .js [data-goal-manual], .js [data-goal-wait] { display: none; }
.js [data-goal-source][data-active-type="COMPANY"] [data-goal-catalogue="COMPANY"],
.js [data-goal-source][data-active-type="PERSONAL"] [data-goal-manual] { display: block; }
.js [data-goal-source][data-active-type=""] [data-goal-wait] { display: flex; }
.goal-cell-title > div + div { margin-top: 6px; }
/* ...BUT NOT WHEN ONLY ONE OF THEM IS SHOWING. `div + div` matches the second
   and third boxes whatever their display, so the 6px meant for the no-script
   stack was also being added to whichever single box the script left visible.
   Measured at 1600px: a company row 51px, a personal row 57px, an empty row
   65px - three heights in one table, on a rule whose own comment promises the
   row shape never changes. */
.js .goal-cell-title > div + div { margin-top: 0; }
html:not(.js) .goal-cell-title .sr-only {
  position: static; display: block; width: auto; height: auto; margin: 0 0 2px;
  overflow: visible; clip: auto; white-space: normal;
  color: var(--text-muted); font-size: var(--fs-xs); font-weight: 700;
}
.goal-entry-number {
  color: var(--accent-text); font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm); font-weight: 700;
}
/* Controls sitting inside grid cells are one size down, like the note input. */
.goal-grid td .control { height: var(--control-h-sm); padding: 0 8px; font-size: var(--fs-sm); }
/* The same height as the controls it stands in for: at 42px against their
   34px it made every untouched row 8px taller than a filled one. */
.goal-pick-wait {
  display: none; align-items: center; min-width: 0; height: var(--control-h-sm); padding: 0 12px;
  background: var(--surface-control); border: 1px solid var(--border-input);
  color: var(--text-muted); font-size: var(--fs-sm);
}
/* The live weight total: the NUMBER, in the number column. The rule that goes
   with it ("tam %100 olmali") sits in the wide left cell as `.total-rule` -
   in here it wrapped to four lines and looked broken. */
.perf-weight { font-variant-numeric: tabular-nums; font-size: var(--fs-lg); }
.perf-weight.is-valid { color: var(--ok-text); }
.perf-weight.is-invalid { color: var(--error-text); }
.total-rule {
  display: block; margin-top: 3px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted);
}

/* A field inside a grid row. The label is still there for a screen reader
   (.sr-only); only the 6px gap beneath it is gone. */
/* A value that is shown where a control would be, because this reader may
   not change it. It keeps the control's box so the row still lines up, and
   drops the white ground so it does not invite a click. */
.control-static {
  display: flex; align-items: center;
  background: var(--surface-sunken);
  border-style: dashed;
  color: var(--text-secondary);
}

.field-bare > .label { display: none; }
.field-bare .control { height: var(--control-h-sm); padding: 0 8px; }
.field-bare textarea.control { height: auto; padding: 6px 8px; }

/* The goal grid. It is the design-system table with narrow numeric columns —
   the source for this screen IS a spreadsheet, so it reads like one. */
/* THE COLUMNS ARE GIVEN WIDTHS. Left to itself the browser sizes a column by
   its widest content, and one catalogue entry runs to 180 characters — it took
   almost the whole table and squeezed the description a person actually types
   down to about ten characters of visible width. */
.goal-grid { table-layout: fixed; }
.goal-grid .control { min-width: 0; }
.goal-num { width: 46px; }
/* "Şirket Ortak Hedefi" plus the select's arrow: 150px cut it to "Şirket Ortak He". */
.goal-type { width: 190px; min-width: 190px; }
.goal-pick { width: 32%; }
.goal-detail { width: 28%; }
.goal-weight { width: 108px; }
.goal-score { width: 92px; }
/* Wide enough for "puanlanmadı" in the total row, which ran past the table's edge. */
.goal-points { width: 124px; }
/* The entry sheet's remove button, one per row (app.js shows it). */
.goal-remove { width: 48px; text-align: center; }
.goal-grid td.goal-remove { padding-inline: 4px; }
.goal-remove .btn-icon { margin-inline: auto; color: var(--text-secondary); }
.goal-remove .btn-icon:hover { color: var(--error-text); }
/* The quota's save closes its boxes at the right, as every form's save does. */
.quota-save { justify-content: flex-end; }

/* A labelled fact strip (projects baseline). Grid, equal heights. */
.chain { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.chain-item { padding: 12px 14px; background: var(--surface-sunken); border-radius: var(--radius-sm); }
.chain-item .label { display: block; margin-bottom: 4px; }
.chain-item strong { font-variant-numeric: tabular-nums; font-size: var(--fs-sm); }

/* The frozen approval chain as PEOPLE - name first, sicil as small print. */
.person-chips { display: grid; gap: 7px; }
.person-chip { padding: 9px 10px; background: var(--surface-sunken); border-radius: var(--radius-sm); }
.person-chip .label { display: block; margin-bottom: 2px; }
.person-chip strong { font-size: var(--fs-sm); }
.person-chip-sicil { margin-left: 6px; color: var(--text-muted); font-size: var(--fs-2xs); }
.person-chip-note { display: block; margin-top: 2px; color: var(--text-muted); font-size: var(--fs-2xs); font-style: italic; }

/* THE NAMED STEP TRACKER - eight steps with names, the current one loud, a
   skipped one greyed with its own note. Discrete items, no widths: CSP. */
.step-tracker {
  list-style: none; margin: 0; padding: 14px 16px;
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
.step-tracker-item { display: flex; align-items: center; gap: 7px; font-size: var(--fs-xs); color: var(--text-muted); }
.step-tracker-dot {
  display: grid; place-items: center; width: 20px; height: 20px; flex: none;
  border-radius: var(--radius-full);
  background: var(--surface-sunken); color: var(--text-muted);
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); font-weight: 700;
}
.step-tracker-item.is-done .step-tracker-dot { background: var(--accent-solid); color: var(--text-on-accent); }
.step-tracker-item.is-current { color: var(--text-body); font-weight: 700; }
.step-tracker-item.is-current .step-tracker-dot { background: var(--text-body); color: var(--surface); }
.step-tracker-item.is-skipped { opacity: .55; }
.step-tracker-note { font-style: italic; }
.step-tracker-compact { display: none; font-variant-numeric: tabular-nums; font-size: var(--fs-xs); color: var(--text-secondary); }
@media (max-width: 760px) {
  .step-tracker-item { display: none; }
  .step-tracker-compact { display: block; }
}

/* Rejections stand apart from approvals in the one action row. */
.perf-actions-divider { width: 1px; align-self: stretch; background: var(--border); margin: 0 4px; }

@media (max-width: 900px) {
  .perf-assignment-grid { grid-template-columns: minmax(0, 1fr); }
  .perf-team-filters { grid-template-columns: minmax(0, 1fr) minmax(150px, .7fr) minmax(140px, .65fr) auto; }
}
@media (max-width: 580px) {
  .sidebar-brand { padding: 14px 20px; }
  .sidebar-back, .sidebar-section, .sidebar-version { display: none; }
  .sidebar-nav { flex-wrap: nowrap; overflow-x: auto; max-width: 100%; padding: 0; scrollbar-width: none; }
  .sidebar-nav::-webkit-scrollbar { display: none; }
  .sidebar-link { flex: 0 0 auto; padding: 12px 16px; }
  .perf-person-picker { grid-template-columns: minmax(0, 1fr); }
  .perf-team-filters { grid-template-columns: minmax(0, 1fr); }
  .perf-filter-actions { width: 100%; }
  .perf-team-filters .btn { width: 100%; height: var(--control-h); }
}

/* ==========================================================================
   Project management

   Three shapes this module needs and nothing else did: a board, a month grid
   and a roadmap. All three are CSS grids or tables — NOT ONE OF THEM SETS AN
   INLINE STYLE, because `style-src 'self'` blocks the attribute and the
   failure is silent.
   ========================================================================== */

/* -- the board ----------------------------------------------------------- */

/* Four equal columns that stretch to the tallest. A column with one card and
   one with nine end level, so the board reads as one object rather than as
   four lists of different lengths. */
.board-cols {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  align-items: stretch;
}
/* Kanban sutunlari sayfanin uzerinde duruyor: dolgusu zeminle ayni olunca
   sutun diye bir sey kalmiyor, yalniz basliklar ve kartlar goruluyor. */
.board-col {
  display: flex; flex-direction: column;
  background: var(--panel-ground); border: 1px solid var(--border);
  border-radius: var(--radius);
  min-height: 160px;
}
.board-col-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border-subtle);
}
.board-col-body { padding: 10px; display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; }
.board-item {
  background: var(--surface); border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}
/* The left edge carries the priority. It is the one thing a person scanning a
   board is actually looking for, and it needs no space of its own. */
.board-item-critical { border-left-color: var(--error); }
.board-item-high     { border-left-color: var(--warn); }
.board-item-medium   { border-left-color: var(--info); }
.board-item-low      { border-left-color: var(--border); }
.board-item-title { font-weight: 600; font-size: var(--fs-sm); }
.board-item-meta {
  margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  font-size: var(--fs-xs); color: var(--text-muted);
}
.board-item-actions { margin-top: 8px; display: flex; gap: 6px; }
.board-empty { color: var(--text-muted); font-size: var(--fs-xs); padding: 8px 2px; }

/* -- the month grid ------------------------------------------------------ */

.month { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--border-subtle); }
.month-head {
  background: var(--surface-head); padding: 8px 6px; text-align: center;
  font-size: var(--fs-xs);
  color: var(--text-muted); font-weight: 700;
}
.month-cell {
  background: var(--surface); min-height: 108px; padding: 6px;
  display: flex; flex-direction: column; gap: 4px;
}
/* Days from the neighbouring months are drawn, not left blank: a grid with
   holes in it stops reading as a calendar. They step back instead. */
.month-cell-outside { background: var(--surface-sunken); opacity: .55; }
.month-cell-today { box-shadow: inset 0 0 0 2px var(--accent); }
.month-day { font-variant-numeric: tabular-nums; font-size: var(--fs-xs); color: var(--text-muted); }
.month-entry {
  font-size: var(--fs-2xs); line-height: 1.3; padding: 3px 5px;
  border-left: 2px solid var(--border); background: var(--surface);
  overflow-wrap: anywhere;
}
.month-entry-task { border-left-color: var(--info); }
.month-entry-meeting { border-left-color: var(--accent); }
.month-entry-projectStart { border-left-color: var(--ok); }
.month-entry-projectEnd { border-left-color: var(--warn); }
.month-entry-done { opacity: .5; text-decoration: line-through; }

/* -- the roadmap --------------------------------------------------------- */

/* Twelve month cells per project, shaded by class.
   NOT A PERCENTAGE-WIDTH BAR: that needs an inline style, which the CSP
   blocks. A month is also the unit these plans are actually made in. */
/* The month cells carry NO horizontal padding, and the rule has to beat
   `.table tbody td`'s own padding — otherwise every month sits in its own
   little box and twelve consecutive months read as twelve dashes rather than
   as one bar. That is the whole difference between a roadmap and a dotted
   line. */
.table thead th.roadmap-month,
.table tbody td.roadmap-month { width: 2.4%; min-width: 22px; padding-inline: 0; }
/* …but the HEADER is text, not a bar. With zero padding the twelve labels ran
   together into "OCAŞUB MARNİS" and the reader could not tell where a month
   started. The cells keep their zero padding so the bars still join. */
.table thead th.roadmap-month {
  padding-inline: 1px; text-align: center;
  font-size: 9px; letter-spacing: 0; overflow: hidden; white-space: nowrap;
}
.roadmap-cell { display: block; height: 18px; background: transparent; }
.roadmap-plan { background: var(--info-tint); border-top: 3px solid var(--info); }
.roadmap-slip { background: var(--error-tint); border-top: 3px solid var(--error); }
.roadmap-done { background: var(--ok-tint); border-top: 3px solid var(--ok); }
.roadmap-now { box-shadow: inset 2px 0 0 var(--accent); }
.roadmap-legend { display: flex; flex-wrap: wrap; gap: 16px; font-size: var(--fs-xs); color: var(--text-muted); }
.roadmap-key { display: inline-flex; align-items: center; gap: 6px; }
.roadmap-swatch { width: 22px; height: 10px; display: inline-block; }

/* -- shared -------------------------------------------------------------- */

/* A progress bar drawn in ten segments — same reasoning as the step bar. */
.meter { display: inline-flex; align-items: center; gap: 2px; }
.meter-seg { width: 9px; height: 8px; background: var(--border); display: inline-block; }
/* THE FILL IS INK, NOT ALARM. It used to be the MKK red, so a task at %100
   drew a full red bar — the one colour the language reserves for "something
   is wrong" spent on "this is finished". Green only when it IS finished. */
.meter-seg-on { background: var(--meter-on); }
.meter-full .meter-seg-on { background: var(--ok); }
.meter-text { margin-left: 8px; font-variant-numeric: tabular-nums; font-size: var(--fs-xs); }

/* Two-column split for a detail screen: main content and a narrower side. */
.split { display: grid; gap: var(--rhythm); grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }
@media (max-width: 1100px) { .split { grid-template-columns: minmax(0, 1fr); } }
.split > * { min-width: 0; }
/* SIDE BY SIDE, THE GRID SPACES THE CARDS - NOT `.card + .card`. That rule
   is for cards stacked in a column, and it also pushed the second card of a
   row 16px below the first: measured on the CMC presets screen, two panes of
   the same 835px height starting at 343 and 359. Stacked below 1100px the
   grid's own gap still separates them. */
.split > .card + .card { margin-top: 0; }

/* TWO PEERS, NOT A MAIN AND A SIDEBAR. `.split` is 2fr/1fr, which is right
   for content-plus-aside and wrong for two lists of equal standing (received
   / given): one card came out half the width of the other for no reason the
   reader could see. Equal columns, equal height. */
.split-even { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
@media (max-width: 1100px) { .split-even { grid-template-columns: minmax(0, 1fr); } }
.split-even > * { height: 100%; }

/* Legend swatches.
   THEY NEED THEIR OWN COLOURS. Reusing `.month-entry-*` here painted a 2px
   left border on a 22px block and the legend came out blank — the classes
   colour a border, which is right on an entry and invisible on a key. */
.legend-task { background: var(--info); }
.legend-meeting { background: var(--accent); }
.legend-projectStart { background: var(--ok); }
.legend-projectEnd { background: var(--warn); }

/* The "why is there no button" panel: three labelled facts, not a paragraph. */
.blocked-step {
  display: grid; gap: 12px; margin-top: 14px; padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
}
@media (min-width: 720px) {
  .blocked-step { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
  .blocked-step > * + * { border-top: 0; padding-top: 0; }
}

/* The per-page "what happens here" list, inside its disclosure. */
.help-list { list-style: none; display: grid; gap: 8px; padding: 0; margin: 0; }
.help-list li {
  position: relative; padding-left: 18px;
  font-size: var(--fs-sm); color: var(--text-secondary);
}
.help-list li::before {
  content: ""; position: absolute; left: 0; top: 8px;
  inline-size: 6px; block-size: 6px; background: var(--accent);
}
/*
 * THE PAGE'S HELP IS A QUIET LINE, NOT A BAR.
 *
 * It was a full-width framed strip between the hero and the first card on
 * every screen: 44px of box saying "Bu sayfada ne yapilir?" before anything
 * the page is for. The help is still one click away; closed, it is a small
 * line of text, and open it is a card of its own.
 */
.disclosure.page-help { border: 0; background: transparent; }
.disclosure.page-help > summary {
  justify-content: flex-start; min-block-size: 24px; padding: 0 2px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-secondary);
}
.disclosure.page-help[open] > summary { border-bottom: 0; }
.disclosure.page-help > .disclosure-body {
  margin-top: 8px; background: var(--surface); border: 1px solid var(--border);
}

/* A content form's action row: the button sits under the fields, not wedged
   between them. `.filters` (a flex bar) is for FILTER controls only. */
.form-actions { margin-top: 16px; }

/* A read-only fact standing in a form row: same rhythm as a field, no box. */
.field-static { display: grid; gap: 4px; align-content: start; }
.field-static strong { min-block-size: var(--control-h); display: flex; align-items: center; }

/* Matrix cells hold a stack of names, not a sentence. */
.cell-name { display: block; font-size: var(--fs-xs); color: var(--text-secondary); }
.cell-empty { color: var(--text-muted); }

/* The chain slot the card is standing on, marked where the people are. */
.person-chip.is-waiting { border-color: var(--border-danger); background: var(--surface-danger); }

/* How far the cards have come through a phase, under its dates. */
.phase-progress { display: block; margin-top: 4px; font-size: var(--fs-2xs); color: var(--text-body); font-weight: 700; }

/* The queue groups by the instruction: said once, above its rows. */
.queue-group + .queue-group { margin-top: 16px; }
.queue-group-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 0 2px 8px;
  font-size: var(--fs-xs); color: var(--text-secondary);
}
.queue-group-count {
  font-size: var(--fs-2xs); font-weight: 700; color: var(--text-body);
  border: 1px solid var(--border); padding: 1px 7px; flex: none;
}

/* ==========================================================================
   Coin mark — the logo column's stand-in
   ==========================================================================
   The original app fetched logos from a CDN; the CSP blocks foreign images
   and an offline machine would show an empty column. The mark is drawn here:
   a fixed colour per symbol (chosen in components.ts, applied as a CLASS
   because style-src forbids the attribute) and the first two letters. */
.coin-mark {
  display: inline-grid; place-items: center; flex: none;
  width: 22px; height: 22px; margin-right: 8px; vertical-align: -6px;
  font-variant-numeric: tabular-nums; font-size: 9px; font-weight: 700;
  letter-spacing: 0; color: var(--text-on-accent);
}
/* Slot 0 was #4e0c11 — a literal copy of the OLD sidebar wine. That colour
   left the application when the rail became a real red, and the copy stayed
   behind pointing at nothing. It is the rail deep step now, so it moves when
   the rail moves (white on it measures 11.99:1). */
.coin-mark-0 { background: var(--sidebar-bg-deep); }
.coin-mark-1 { background: var(--coin-1); }
.coin-mark-2 { background: var(--coin-2); }
.coin-mark-3 { background: var(--coin-3); }
.coin-mark-4 { background: var(--coin-4); }
.coin-mark-5 { background: var(--coin-5); }
.coin-mark-6 { background: var(--coin-6); }
.coin-mark-7 { background: var(--coin-7); }
.coin-mark-8 { background: var(--coin-8); }
.coin-mark-9 { background: var(--coin-9); }
.coin-mark-lg {
  width: 44px; height: 44px; margin-right: 16px; vertical-align: 0;
  font-size: 14px;
}
.page-head .coin-mark-lg { align-self: center; }
/*
 * THE MARK AND THE NAME ARE CENTRED ON EACH OTHER, not on a guessed baseline.
 *
 * `.coin-cell` was used by the volume and CMC tables and defined NOWHERE, so
 * the mark was placed by its own `vertical-align: -6px` against whatever text
 * stood beside it. Measured on the first row of both tables: the name's line
 * centred at 816.5 and 822.5, the mark at 826 and 832 - every mark 9.5px low.
 * A flex row centres the two boxes whatever the font, and `vertical-align` is
 * ignored inside it, so the number above stops mattering here.
 */
.coin-cell { display: inline-flex; align-items: center; }

/* -- CMC ------------------------------------------------------------------- */
/* The market table, shown at once, in a panel that scrolls with its header row
   pinned - the original's table-wrap. The inner scroller is released so the
   pinned row sticks to THIS box and not to one that never scrolls. */

/* The presets workspace: the catalogue is the narrower pane, as in the original. */
.split.split-2-3 { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); align-items: stretch; }
@media (max-width: 1100px) { .split.split-2-3 { grid-template-columns: minmax(0, 1fr); } }

/* A search box or the name box, with what belongs beside it, on one line. */
.pane-tools { display: flex; align-items: center; gap: 8px; }
.pane-tools > .field { flex: 1; min-width: 0; margin: 0; }
.pane-tools > .panel-note, .pane-tools > .btn { flex: none; }
/*
 * THE COUNT ROW PUSHES WITH SPACE, NOT BY STRETCHING THE CHIP.
 *
 * Making `.panel-note` take the slack did put the button on the right edge,
 * and it also turned a small bordered chip into a full-width bordered box
 * that read as another empty input - two of them stacked under the real
 * search box. The chips keep their own width and `margin-left: auto` on
 * whatever follows does the pushing.
 */
.pane-tools > .panel-note ~ .btn,
.pane-tools > .panel-note ~ .inline-form { margin-left: auto; }
/* Each list scrolls inside its own pane, so the page does not grow five
   hundred rows tall. */
.pane-scroll {
  max-height: 610px; overflow-y: auto;
  border: 1px solid var(--border-subtle);
  padding: 4px;
}

/*
 * A COIN IS A CARD, NOT A LINE - and this is the measurement that was wrong.
 *
 * The first version of this port drew one coin as one flat row: tick, a
 * two-letter tile, symbol, name and rank all on a single baseline, packed
 * three to a pane. The original stacks them - the logo at 30px beside the
 * symbol, the name UNDER the symbol in smaller grey - inside a bordered tile
 * 56 pixels tall. Side by side the difference is not decoration: the flat
 * version gives a name about twelve characters before it clips ("Tether
 * U..."), and this one gives it the whole width of the tile.
 *
 * THE NUMBERS ARE MEASURED FROM THE ORIGINAL, not chosen here:
 * `src/stil/catalog-ui.css` sets 56px minimum (62 on a wide screen), 30px
 * logos (32 wide), 9px padding, 6px between tiles, symbol 12px over name 10.
 * The original is the declared visual reference and its
 * measurements are not ours to tune.
 */
/* THE COLUMNS ARE FIXED, NOT AUTO-FLOWED: tick, rank plate, mark, text,
   state. A catalogue row that is already in the preset carries a badge in the
   last one and a row you can still add leaves it empty - declaring both means
   the marks and names line up down the pane either way. */
.pick-tile {
  display: grid;
  grid-template-columns: auto auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  min-height: 56px;
  padding: 9px 10px;
  border: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
  font-size: var(--fs-sm);
}
.pick-tile:hover { border-color: var(--border-hover); background: var(--surface-hover); }

/* THE MARK IS ROUND AND 30px, because a coin logo is a round badge
   everywhere it is ever seen. The drawn two letters stay underneath it for
   a coin whose picture has not been downloaded. */
.pick-tile .coin-mark {
  width: 30px; height: 30px; margin-right: 0;
  border-radius: var(--radius-full);
  font-size: 12px;
}
.pick-tile .coin-mark-img { border-radius: var(--radius-full); }

/* THE SYMBOL AND THE NAME ARE ONE COLUMN, stacked. `min-width: 0` on the
   grid cell is what lets the ellipsis happen at all - without it the cell
   sizes to the longest name and pushes the rank off the tile. */
.pick-tile-text { display: grid; min-width: 0; gap: 2px; }
.pick-tile .coin {
  min-width: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--text-body);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pick-tile-sub {
  min-width: 0; color: var(--text-muted); font-size: var(--fs-xs);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* A row that cannot be ticked still KEEPS the tick's column. Hiding it with
   `display: none` would take the column with it and stagger the catalogue
   into two indents - one for the coins you can add, one for the ones already
   in the preset. `visibility` leaves the box and its width behind. */
.pick-tile input.is-placeholder { visibility: hidden; }

/*
 * THE RANK LEADS THE CATALOGUE ROW, as a tinted plate on the left.
 *
 * "#1" is why somebody is reading the top-500 list at all, and as small grey
 * text at the far right of the tile it was the last thing the eye found. The
 * original gives it a 38x26 plate in the accent tint, first in the row.
 */
.pick-tile-rank {
  display: grid; place-items: center;
  width: 38px; height: 26px;
  border: 1px solid var(--border-warm);
  background: var(--accent-tint);
  color: var(--accent-text);
  font-size: var(--fs-2xs); font-weight: 800;
}
.pick-tile-rank:empty { border-color: transparent; background: transparent; }

/* The selection pane carries no rank plate, so its rows are one column
   narrower - tick, mark, text. */
.pick-grid-compact .pick-tile { grid-template-columns: auto auto minmax(0, 1fr); }

/* TWO COLUMNS, NOT THREE. The original's preset pane is `repeat(2, 1fr)`;
   at three a 56px tile has no room left for the name beside the logo. */
.pick-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
@media (max-width: 860px) { .pick-grid-2 { grid-template-columns: minmax(0, 1fr); } }

/* The catalogue is the narrow pane, so its rows run one to a line. */
.pick-grid-1 { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }

/*
 * A TICKED ROW IS THE ORDINARY STATE HERE, SO IT WEARS NO COLOUR. The preset
 * IS its ticked boxes; seventy-six tinted rows were a wall. What is about to
 * CHANGE on save is what shows: a coin to be added, a coin to be removed.
 */
.pick-grid-compact .pick-tile:has(input:checked) { background: var(--surface-sunken); }
.pick-grid-1 .pick-tile:has(input[name="coin"]:checked) {
  border-color: var(--ok); background: var(--ok-tint);
}
.pick-grid-draft .pick-tile:has(input:not(:checked)) :is(.coin, .pick-tile-sub) {
  color: var(--text-muted); text-decoration: line-through;
}


/* Only the BOTTOM margin is reset: `margin: 0` here came later than the
   section's own spacing and cancelled it - the report measured flush against
   its button (642 / 642). The top margin is the section's to give. */
.code-block {
  margin-bottom: 0; padding: 14px 16px;
  background: var(--surface-sunken); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: var(--fs-xs); line-height: 1.6;
  color: var(--text-body);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 380px; overflow-y: auto;
}
/* The downloaded logo, laid OVER the drawn mark: a picture that fails to load
   leaves the letters showing. Its ground is the surface, not the mark's
   colour - most logos are transparent PNGs and read wrong on a coloured tile. */
.coin-mark { position: relative; overflow: hidden; }
.coin-mark-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; background: var(--surface);
}

/* -- CMC parity: the table viewer, the toasts' heads and holds, ---------------
   the asked-twice "Tümünü çıkar", the draft history (components.ts `viewer`,
   `toast({title, hold})`, `confirmAction({disabled})`, `draftHistory`). */

/* A panel over the page. Without script it unfolds in place under its
   button; with script (app.js `data-viewer`) the open panel is laid over the
   page on a backdrop, as the original's table viewer was. */
.viewer > summary { list-style: none; }
.viewer > summary::-webkit-details-marker { display: none; }
.viewer-backdrop { display: none; }
.viewer-panel {
  margin-top: 12px;
  border: 1px solid var(--border); background: var(--surface);
}
.viewer-head {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px var(--card-p); border-bottom: 1px solid var(--border-subtle);
}
.viewer-close { display: none; }
.js .viewer-close { display: inline-flex; }
/* A scrim is dark in both palettes: over the dark theme a tint of the text
   colour would lay a pale haze on the page instead of dimming it. */
.js .viewer[open] > .viewer-backdrop {
  display: block; position: fixed; inset: 0; z-index: 150;
  background: rgb(8 12 24 / .55);
}
/* The panel hugs what it holds and stands in the middle; only a body taller
   than the window scrolls, inside, under a head and a foot that stay. */
.js .viewer[open] > .viewer-panel {
  position: fixed; z-index: 151; inset: 32px; margin: auto; max-width: 1280px;
  height: fit-content; max-height: calc(100dvh - 64px);
  display: flex; flex-direction: column; box-shadow: var(--shadow-overlay);
}
.js .viewer[open] .viewer-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.viewer-foot {
  display: flex; justify-content: flex-end; align-items: center; gap: 8px; flex: none;
  padding: 12px var(--card-p); border-top: 1px solid var(--border-subtle);
}
.viewer-foot form { margin: 0; }
/* A grade table's search and choices: one line, the count of what is left at its end. */
.grade-filters { align-items: center; }
.grade-filters .field { min-width: 0; }
.grade-filters .field:has(input[type="search"]) { flex: 1 1 260px; min-width: 220px; max-width: 360px; }
.grade-filters select { min-width: 170px; }
.grade-filters .grade-filter-count { margin: 0 0 0 auto; }
.grade-filter-body { padding-top: 0; }
.viewer-body .grade-filters { margin-top: 12px; }
/* Over a table only the rows scroll: the counts above and the foot stay put. */
.js .viewer[open] .viewer-body:has(> .table-pane) { display: flex; flex-direction: column; overflow: hidden; }
.js .viewer[open] .viewer-body > .card-body { flex: none; }
.js .viewer[open] .viewer-body > .table-pane { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.js .viewer[open] .viewer-body > .table-pane > .scroll-x { flex: 1 1 auto; min-height: 0; max-height: none; }
html.viewer-open { overflow: hidden; }
/* THE PAGE'S ARRIVAL FADE HOLDS ITS LAST FRAME (`both`), and an element held
   at an animated opacity is a stacking context of its own: the panel's
   z-index then counted only inside <main>, and the sticky top strip was
   drawn over it. While a viewer is open the finished fade lets go of its
   frame — changing the fill does not replay it. */
html.viewer-open .main[data-enter] { animation-fill-mode: none; }
@media (max-width: 720px) { .js .viewer[open] > .viewer-panel { inset: 12px; } }

/* A notice with a heading: the original's "Preset kaydedildi" over its
   detail. The heading carries the weight, the detail steps back. */
.toast-title { display: block; margin-bottom: 2px; font-weight: 700; }
.toast:has(.toast-title) .toast-text { font-weight: 500; }

/* The original's two holds: a confirmation leaves after 3.8 s, an error
   stays 12 s to be read. The hub's 7 s stays the default. */
/* Only the hold changes; the fade, the slide and the hairline read it. */
.toast-brief { --toast-hold: 3.8s; }
.toast-long { --toast-hold: 12s; }
/* Two at once — a failed fetch and "Bağlantı testi önerilir" — stack in the
   corner (.toast-region is already a column), as the original stacked them. */

/* "Tümünü çıkar" is asked twice, and still shares its line evenly with
   "Tümünü ekle" (`.btn-split`): the summary takes the column. */
.btn-split > .confirm { display: block; min-width: 0; }
.btn-split > .confirm > summary {
  width: 100%; min-width: 0; height: auto; min-height: var(--control-h);
  padding: 6px 12px; white-space: normal; text-align: left; line-height: 1.3;
}
/* Nothing to act on ("Çıkarılacak yok"): drawn, never opened. */
.confirm > summary.is-disabled { opacity: .55; pointer-events: none; cursor: default; }

/* A pane whose every row the filter hid is not drawn as an empty box above
   "Aramanızla eşleşen coin bulunamadı." */
.pane-scroll:has(> .pick-list):not(:has(li:not([hidden]))) { display: none; }

/* "↶ Geri al" / "↷ İleri al" sit with the pane's other small buttons. */
.draft-history { display: inline-flex; gap: 6px; }
.draft-history:not(:has(.btn:not([hidden]))) { display: none; }

/* -- Mode switch: two ways of doing one job, the current one underlined ---- */

.mode-switch {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  border: 1px solid var(--border); background: var(--surface);
}
.mode-switch-item {
  display: flex; flex-direction: column; gap: 2px; padding: 12px 16px;
  color: var(--text-body); text-decoration: none; border-left: 1px solid var(--border-subtle);
}
.mode-switch-item:first-child { border-left: 0; }
.mode-switch-item span { font-size: var(--fs-xs); color: var(--text-muted); }
.mode-switch-item:hover { background: var(--surface-sunken); }
.mode-switch-item[aria-current="page"] { box-shadow: inset 0 -3px 0 var(--accent); }

/* -- Muhasebe: the row of buttons under an edge-to-edge table --------------- */

/* A flush card gives its table no padding, so a button row after the table
   started 1px from the card edge while the cells above it were padded
   (measured: x 303 in a card at x 302). The row takes the card's padding and
   a hairline. The analysis screen's row also stays on screen: with more than
   six source columns the only button on the page fell below the window. */
/* The action bar at the foot of a flush card. Named for what it does: four
   of its seven users were Akit while it was called `.acc-actions`. The two
   variants below stay accounting's, because that is what they are. */
.card-foot { padding: 12px var(--card-p); border-top: 1px solid var(--border-subtle); }
.acc-actions-sticky { position: sticky; bottom: 0; z-index: 2; background: var(--surface); }
/* The format screen's one button row sits under ALL the sheet cards, outside
   any of them, so it carries its own frame. */
.acc-actions-bar { border: 1px solid var(--border); }
/* The type box's longest choice, "— Bu kolonu alma —", was cut to
   "— Bu kolonu alm" at the width the table gave it. */
form[action$="/build"] td select,
form[action$="/map"] td select { min-width: 13rem; }

/* The sheet's own choices (heading row, take this sheet) sit above its
   edge-to-edge tables, so they take the card's padding like the button row. */
.acc-sheet-tools { padding: 12px var(--card-p); border-bottom: 1px solid var(--border-subtle); align-items: flex-end; }
.acc-sheet-tools .field { min-width: 16rem; }
/* A note inside a flush card, which has no padding of its own. Named for
   what it does, not for the module that needed it first: three of its
   users were Akit while it was called `.acc-preview-note`. */
.flush-note { padding: 8px var(--card-p) 0; }

/* The clause editor's reference wording: the LONGEST value in that table,
   and without this the widest column was the keyword list next to it. */
.ctr-rule-text { width: 42%; }
/* The preview's row number is a submit button on the format screen and a link
   on the mapping screen. At button height (34px) the same preview was 16px
   taller per row on one screen than the other; a row number is a number, not
   a control that sets the row's height. */
.table td > button[name="pick"] { height: 20px; padding: 0 6px; }

/* The preview: the heading row is what the reader is confirming, so it is the
   one row that stands out; the report lines above it are quieter. */
.acc-preview-head td { background: var(--surface-sunken); font-weight: 700; }
.acc-preview-head td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.acc-preview-above td { color: var(--text-muted); }
.acc-preview-cell { display: inline-block; max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* -- Akit: iki versiyon arasindaki fark ------------------------------------ */

/* A paragraph of the comparison. The kind chip on the left, the text on the
   right; a changed paragraph carries the previous wording underneath so the
   reader never has to hold two screens in their head. */
.ctr-para { display: grid; grid-template-columns: 7.5rem 1fr; gap: 0 16px; padding: 10px var(--card-p); border-bottom: 1px solid var(--border-subtle); }
.ctr-para:last-child { border-bottom: 0; }
.ctr-para-kind { font-size: var(--fs-xs); font-weight: 700; color: var(--text-muted); padding-top: 2px; }
.ctr-para-text { min-width: 0; }
.ctr-para-note { display: block; margin-top: 4px; font-size: var(--fs-xs); color: var(--text-muted); }
/* The previous wording of a changed paragraph: quieter, and marked as past. */
.ctr-para-before { display: block; margin-top: 6px; padding-left: 10px; border-left: 2px solid var(--border); font-size: var(--fs-sm); color: var(--text-muted); }

/* A changed paragraph is the one the reader came for, so it is the one that
   is marked; identical paragraphs stay plain. */
.ctr-changed { background: var(--surface-sunken); }
.ctr-changed .ctr-para-kind { color: var(--accent-text); }

/* THE WORD DIFF. Colour is NOT the only carrier: added text is underlined and
   deleted text is struck through, so the two are still told apart in a
   printout, in a screenshot and by a reader who does not see the difference
   between red and green. */
.ctr-add { background: var(--ok-tint); color: var(--ok-text); text-decoration: underline; text-decoration-thickness: 1px; }
.ctr-del { background: var(--error-tint); color: var(--error-text); text-decoration: line-through; }

/* -- Akit: belgenin Word gorunumu ------------------------------------------ */

/* A PAGE, NOT A PREVIEW OF ONE. The sheet is A4-shaped with the corporate
   margin, and the document's OWN page size and margins are written above it in
   words: an inline style is forbidden here (the content security policy blocks
   the attribute, .claude/rules/arayuz.md), so a sheet that claimed to be drawn
   to the document's exact millimetres would be claiming something it cannot
   do. What the sheet does carry is what a class can carry: alignment, weight,
   the common point sizes and the three fonts these contracts actually use. */
.ctr-page {
  max-width: 21cm; margin: 0 auto; padding: 2.5cm;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-lift);
  font-family: "Times New Roman", Times, serif; font-size: 11pt; line-height: 1.5;
  color: var(--text-body);
}
.ctr-page p { margin: 0 0 6pt; }

/* The reader's own paragraph numbers come from Word, not from the browser:
   an ordered list would renumber them and quietly disagree with the document. */
.ctr-num { display: inline-block; min-width: 2.2em; font-variant-numeric: tabular-nums; }

.ctr-b { font-weight: 700; }
.ctr-i { font-style: italic; }
.ctr-u { text-decoration: underline; }
.ctr-strike { text-decoration: line-through; }
.ctr-hidden { opacity: .55; }

.ctr-left { text-align: left; }
.ctr-right { text-align: right; }
.ctr-center { text-align: center; }
.ctr-both { text-align: justify; }

/* The point sizes these contracts use; anything else keeps the page's own. */
.ctr-sz-8 { font-size: 8pt; }
.ctr-sz-9 { font-size: 9pt; }
.ctr-sz-10 { font-size: 10pt; }
.ctr-sz-11 { font-size: 11pt; }
.ctr-sz-12 { font-size: 12pt; }
.ctr-sz-14 { font-size: 14pt; }
.ctr-sz-16 { font-size: 16pt; }
.ctr-sz-18 { font-size: 18pt; }
.ctr-font-times { font-family: "Times New Roman", Times, serif; }
.ctr-font-arial { font-family: Arial, Helvetica, sans-serif; }
.ctr-font-calibri { font-family: Calibri, Candara, Segoe, sans-serif; }

/* A tab and a manual line break are characters in Word; on screen they are
   space, and a reader who cannot see them cannot tell why a line moved. */
.ctr-tab { display: inline-block; min-width: 2em; }
.ctr-object { color: var(--text-muted); font-style: italic; }

/* A paragraph the application may not rewrite: shown, and marked as such. */
.ctr-locked { position: relative; background: var(--warn-tint); }
.ctr-lock-note { display: block; font-size: var(--fs-2xs); color: var(--warn-text); font-style: normal; }

/* Header and footer are outside the body: quieter, and labelled. */
.ctr-band { padding: 8px 12px; border: 1px dashed var(--border); color: var(--text-muted); font-size: var(--fs-sm); }
.ctr-band-label { display: block; font-size: var(--fs-xs); font-weight: 700; }

/* -- duzenleme kipi -------------------------------------------------------- */

/* The toolbar sits above the sheet, not on it: a bar floating over the page
   would cover the first line of the contract, which is where a heading is. */
.ctr-tools { padding: 12px var(--card-p); border: 1px solid var(--border); background: var(--surface); }
.ctr-tools .row + .field-hint { margin-top: 8px; }

/* An editable paragraph shows where the caret may go, without shouting. */
.ctr-page p[contenteditable="true"] { outline: 1px dashed var(--border); outline-offset: 3px; }
.ctr-page p[contenteditable="true"]:focus { outline: 2px solid var(--accent); }

/* A paragraph marked for deletion: struck through and no longer writable, so
   the reader can see the decision and undo it before saving. */
.ctr-removed { text-decoration: line-through; color: var(--error-text); background: var(--error-tint); }

/* A table inside the document keeps the document's own look, not the hub's. */
.ctr-page table { width: 100%; border-collapse: collapse; margin: 0 0 6pt; }
.ctr-page td { border: 1px solid var(--border); padding: 4pt 6pt; vertical-align: top; }


.acc-warning { color: var(--text-muted); }

/* -- Muhasebe: Kolon Tasarımcısı ------------------------------------------ */

/* The options box follows the type choice on the spot: it is drawn in every
   row and shown only while that row's type is Liste. Without :has() both
   stay visible - an unused box, never a missing one. */
.acc-list-none { display: none; }
@supports selector(:has(*)) {
  tr:not(:has(option[value="list"]:checked)) .acc-list-options { display: none; }
  tr:not(:has(option[value="list"]:checked)) .acc-list-none { display: inline; }
}

/* ==========================================================================
   KULLANIM KILAVUZU — contents on the left, numbered topics on the right

   The shape the user pointed at (the Akit application's guide), in this
   palette: part dividers, a numbered card per topic, fact tiles with the
   accent strip, numbered steps, and screenshots whose markers match the
   numbered legend under them.
   ========================================================================== */
.manual-book {
  display: grid; grid-template-columns: 250px minmax(0, 1fr);
  gap: 20px; align-items: start;
}
.manual-side {
  position: sticky; top: 88px;
  max-height: calc(100vh - 104px); overflow-y: auto; scrollbar-width: thin;
}
.manual-toc {
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-card); padding: 4px 0 10px;
}
.manual-toc-part {
  padding: 12px 16px 4px; color: var(--text-muted);
  font-size: 12px; line-height: 16px; font-weight: 700;
}
.manual-toc-link {
  display: flex; gap: 4px; padding: 6px 14px 6px 13px;
  border-left: 3px solid transparent;
  color: var(--text-body); font-size: 13px; line-height: 18px; text-decoration: none;
}
.manual-toc-link:hover { border-left-color: var(--accent); background: var(--surface-hover); color: var(--accent-text); }
.manual-toc-link.is-active {
  border-left-color: var(--accent); background: var(--surface-selected);
  color: var(--accent-text); font-weight: 700;
}
.manual-no { flex: 0 0 22px; color: var(--text-muted); font-weight: 700; font-variant-numeric: tabular-nums; }
.manual-toc-link.is-active .manual-no,
.manual-toc-link:hover .manual-no { color: var(--accent-text); }

.manual-content { display: flex; flex-direction: column; gap: 16px; min-width: 0; container: manual / inline-size; }
.manual-divider { display: flex; gap: 10px; align-items: center; margin-top: 18px; }
.manual-divider:first-child { margin-top: 0; }
.manual-divider span {
  color: var(--text-muted); font-size: 13px; line-height: 16px;
  font-weight: 700; letter-spacing: .08em; white-space: nowrap;
}
.manual-divider b {
  color: var(--accent-text); font-size: 17px; line-height: 24px; white-space: nowrap;
}
.manual-divider::after { content: ""; flex: 1; height: 2px; background: var(--accent); opacity: .3; }

.manual-topic { scroll-margin-top: 88px; }
.manual-topic > .card-head { gap: 12px; align-items: center; }
.manual-topic-no {
  flex: 0 0 36px; display: grid; place-items: center; width: 36px; height: 36px;
  border-radius: var(--radius-full); background: var(--accent-solid);
  color: var(--text-on-accent); font-size: 16px; font-weight: 800;
}
.manual-body { font-size: 14px; line-height: 1.7; }
.manual-lead { max-width: 820px; }

.manual-facts { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.manual-fact {
  border: 1px solid var(--border); border-top: 3px solid var(--accent);
  background: var(--surface); padding: 12px 14px;
}
.manual-fact b { display: block; font-size: 14px; line-height: 20px; }
.manual-fact span { display: block; margin-top: 4px; color: var(--text-secondary); font-size: 13px; line-height: 20px; }

.manual-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.manual-steps li { display: flex; gap: 14px; align-items: flex-start; }
.manual-steps li > span:last-child { padding-top: 3px; max-width: 820px; }
.manual-step-no {
  flex: 0 0 30px; display: grid; place-items: center; width: 30px; height: 30px;
  border-radius: var(--radius-full); background: var(--accent-tint);
  color: var(--accent-text); font-size: 13px; font-weight: 800;
}

.manual-figure { margin: 0; border: 1px solid var(--border); background: var(--surface-sunken); }
.manual-shot { display: block; padding: 8px; cursor: zoom-in; }
.manual-shot:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -4px; }
.manual-shot-frame {
  position: relative; display: block; max-width: 1040px; margin: 0 auto;
  background: var(--surface); border: 1px solid var(--border-subtle); box-shadow: var(--shadow-card);
}
.manual-shot-frame img { display: block; width: 100%; height: auto; }
.manual-marks { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* RED MARKS ON A RED INTERFACE: the screenshots carry the interface's own red
   (filled buttons, red-topped cards, late dates), so a bare red frame over a
   red button reads as part of the screen. What keeps a mark an annotation is
   the WHITE HALO under every frame and the white rim round every number: no
   element of the interface has that outline. The faint fill lifts the marked
   region off its neighbours. White, not --surface: the screenshots are always
   light, and in dark mode --surface would draw a black rim on a white picture. */
.manual-mark-halo { fill: none; stroke: #ffffff; stroke-width: 6; stroke-opacity: .9; vector-effect: non-scaling-stroke; }
.manual-mark-box { fill: var(--accent-solid); fill-opacity: .06; stroke: var(--accent-solid); stroke-width: 2.5; vector-effect: non-scaling-stroke; }
.manual-mark-dot { fill: var(--accent-solid); stroke: #ffffff; stroke-width: 2.5; vector-effect: non-scaling-stroke; }
.manual-mark-no { fill: var(--text-on-accent); font-family: var(--font-sans); font-weight: 800; }
.manual-figure figcaption { border-top: 1px solid var(--border); background: var(--surface); padding: 12px 18px 14px; }
.manual-figure-title { font-size: 14px; line-height: 20px; font-weight: 700; color: var(--text-body); }
.manual-figure-title span { margin-left: 8px; color: var(--text-muted); font-size: 13px; font-weight: 400; }
.manual-legend {
  list-style: none; margin: 10px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 28px;
}
.manual-legend li { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; line-height: 20px; }
.manual-legend b {
  flex: 0 0 22px; display: grid; place-items: center; width: 22px; height: 22px;
  border-radius: var(--radius-full); background: var(--accent-solid);
  color: var(--text-on-accent); font-size: 13px; line-height: 1;
}
.manual-missing { padding: 32px 18px; color: var(--text-muted); text-align: center; }

/* CLASS NAMES ARE manual-*, NOT guide-*: the performance module's older guide
   page used .guide-side, .guide-defs, .guide-note and friends, and the two
   sets of rules met on both pages. That page and its block are gone; the
   guide-* names stay unused so the clash cannot come back. */
.manual-defs { margin: 0; border: 1px solid var(--border); }
.manual-defs > div { display: grid; grid-template-columns: minmax(170px, 250px) minmax(0, 1fr); align-items: stretch; }
.manual-defs > div + div { border-top: 1px solid var(--border-subtle); }
.manual-defs dt,
.manual-defs dd { margin: 0; padding: 9px 14px; font-size: 13px; line-height: 20px; }
.manual-defs dt { background: var(--surface-sunken); font-weight: 700; }
.manual-list { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 4px; }
.manual-list li { list-style: disc; max-width: 820px; }
.manual-note {
  border-left: 3px solid var(--info); background: var(--info-tint);
  padding: 9px 14px; font-size: 13px; line-height: 20px;
}
.manual-faq { display: flex; flex-direction: column; gap: 8px; }
.manual-faq .disclosure summary { font-weight: 700; }

@container manual (max-width: 760px) {
  .manual-legend { grid-template-columns: 1fr; }
  .manual-defs > div { grid-template-columns: 1fr; }
}
@media (max-width: 1080px) {
  .manual-book { grid-template-columns: 1fr; }
  .manual-side { position: static; max-height: none; }
}

/* The enlarged picture: script-only, drawn over everything, any click closes. */
.manual-zoom {
  position: fixed; inset: 0; z-index: 60; overflow: auto;
  background: color-mix(in srgb, var(--text-body) 86%, transparent);
  padding: 40px 24px 24px; cursor: zoom-out;
}
.manual-zoom:focus { outline: none; }
.manual-zoom-close { position: fixed; top: 10px; right: 24px; z-index: 61; }
.manual-zoom .manual-shot-frame { max-width: min(1440px, 100%); box-shadow: var(--shadow-overlay); }
/* ON A PHONE THE INLINE PICTURE IS A THUMBNAIL (a 1100 px screenshot in a
   340 px column is a quarter of its size), so enlarging must not shrink it
   back to the screen's width: it opens near its own size and scrolls both
   ways, numbers and text at a readable size. */
@media (max-width: 760px) {
  .manual-zoom { padding: 52px 12px 12px; }
  .manual-zoom .manual-shot-frame { width: 960px; max-width: none; }
}

/* -- manual: zoom and reading marker (app.js, data-manual-zoom / -book) ----
   While the enlarged picture is open the page behind it does not scroll: the
   wheel belongs to the picture. The book's end marker is the scroll-spy's
   sentinel and must take no room - it cancels the column's own gap. */
html.manual-zoom-open { overflow: hidden; }
.manual-end { display: block; height: 1px; margin-top: -17px; pointer-events: none; }

/* The "?" in the top strip: a circled question mark, the guide's own sign. */
.topbar-help-mark {
  display: grid; place-items: center; width: 19px; height: 19px;
  border: 1.5px solid currentColor; border-radius: var(--radius-full);
  font-size: 13px; font-weight: 800; line-height: 1;
}

/* ==========================================================================
   VERİ SAĞLIĞI — uygulama kartı, içinde kaynak satırları

   Eskiden beş kaynak beş ayrı karttı ve her kart kendi içinde bir durum
   kutusu, bir olgu listesi ve açık bir tarih listesi taşıyordu: sayfa 2600px
   sürüyordu ve yarısı tekrardı (aynı "geri getirilemez" paragrafı dört kez,
   aynı borsa ipucu üç kez). Şimdi uygulama başına BİR kart, kaynaklar onun
   içinde satır. Satırın uzunu — tarihler, deneme kaydı — katlanıyor.
   ========================================================================== */

.health-app + .health-app { margin-top: var(--rhythm); }

/* Uygulamanın kimliği: ana menüdeki kutucukla aynı renk çipi, aynı ikon.
   Renk `tile-<departman>` sınıfından geliyor (§6.1 — satır içi style yok). */
.health-app-icon {
  display: grid; place-items: center; width: 34px; height: 34px; flex: none;
  background: var(--tile-color, var(--accent)); color: var(--text-on-accent);
  border-radius: var(--radius-sm);
}

/* Kaynak listesi kartın gövdesini boydan boya kaplıyor: satırlar arasındaki
   ayırıcı kartın kenarına kadar gitsin, kutu içinde kutu olmasın. */
.health-sources { list-style: none; margin: 0; padding: 0; }
.health-source {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 16px var(--card-p);
  border-left: 3px solid var(--text-muted);
}
.health-source + .health-source { border-top: 1px solid var(--border-subtle); }
/* Sol kenar durumu taşıyor — `.status` kartındaki dille aynı. */
.health-source-ok    { border-left-color: var(--ok); }
.health-source-warn  { border-left-color: var(--warn); }
.health-source-error { border-left-color: var(--error); }
.health-source-idle  { border-left-color: var(--border); }

.health-source-main { min-width: 0; flex: 1; }
.health-source-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.health-source-head strong { font-size: var(--fs-md); font-weight: 600; }
.health-source-hint {
  margin-top: 2px; font-size: var(--fs-xs); color: var(--text-muted);
}
/* Tek satır olgu: "Son başarılı: … · 7 gün kayıtlı · 26.08 – 07.09".
   Üst üste dizilmiş üç etiket kartı uzatan şeydi. */
.health-source-facts {
  margin-top: 6px; font-size: var(--fs-sm); color: var(--text-secondary);
}
.health-source-act { flex: none; padding-top: 2px; }

/* Eksik gün yoksa söylenecek tek şey bu; bir kutu açmaya değmez. */
.health-clear {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 10px; font-size: var(--fs-sm); color: var(--ok-text);
}

.health-source .disclosure, .health-app-foot .disclosure { margin-top: 10px; }
.health-gap-summary { display: inline-flex; align-items: center; gap: 8px; }

/* Çökük yüzey: tarihler gövdeden ayrılsın, ayrı bir kart açmadan
   (üçüncü katman). */
.health-gap-list {
  list-style: none; margin: 0 0 12px; padding: 10px 12px;
  background: var(--surface-sunken); border: 1px solid var(--border-subtle);
  display: grid; gap: 4px; max-height: 260px; overflow-y: auto;
}
.health-gap-list li {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 13px; line-height: 1.5;
}

/*
 * CUKURUN ICINDE CUKUR OLMAZ — --panel-ground SIRAYLA DEGISIR.
 *
 * Bu serit kendisi cukur tonda, ve kartin icinde oldugu icin icindeki
 * katlanir kutu da cukur tonu aliyordu: ikisi ayni renk, kontrast 1.000.
 * Kendi tonunu boyayan bir kap, cocuklari icin degiskeni geri cevirir.
 * Yeni bir cukur kap eklendiginde ayni satir ona da gerekiyor.
 */
.health-app-foot { --panel-ground: var(--surface); }
.health-app-foot {
  padding: 12px var(--card-p) 16px;
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
}

/* Dar ekranda düğme satırın altına iner; 1180'de sıkışıp taşmasın. */
@media (max-width: 900px) {
  .health-source { flex-direction: column; }
  .health-source-act { padding-top: 0; }
}

/* -- health: rebuilt pieces (ui/health-panel.ts) -------------------------------
   The stored error of a CURRENT failure, verbatim, under the facts line. The
   warning colour is the text's, not a box's: the row's left edge already
   says the row is in trouble, a second frame inside it would shout. */
.health-source-problem {
  display: flex; align-items: flex-start; gap: 6px;
  margin: 6px 0 0; font-size: var(--fs-sm); line-height: 1.45;
  color: var(--error-text); overflow-wrap: anywhere;
}
.health-source-problem svg { flex: none; margin-top: 3px; }
.health-source-warn .health-source-problem { color: var(--warn-text); }
.health-source-hint + .health-source-hint { margin-top: 4px; }
.health-app-foot .health-source-hint { margin: 0; }
.health-app-foot .health-source-hint + .health-source-hint { margin-top: 4px; }
.health-source-facts { margin-bottom: 0; }
.health-source-hint { margin-bottom: 0; }
.status-body ul a { font-weight: 600; }

/* ==========================================================================
   TREE — a hierarchy as indented, connected lists (components.ts `tree`)

   The organisation chart is its first reader. Indented rather than drawn
   top-down: eighty people, five levels, fifteen wide at the widest level,
   and a top-down drawing that wide scrolls sideways on every screen. The
   connectors are borders on the list items, so nothing is positioned by
   script and the chart prints.
   ========================================================================== */
.tree, .tree-children { list-style: none; margin: 0; padding: 0; }
.tree-children { margin-left: 18px; padding-left: 18px; border-left: 1px solid var(--border); }
.tree-item { position: relative; margin: 0; }
.tree-item + .tree-item { margin-top: 6px; }
.tree-children > .tree-item:first-child { margin-top: 6px; }
/* The elbow from the parent's line into this row. */
.tree-children > .tree-item::before {
  content: ""; position: absolute; left: -18px; top: 22px;
  width: 16px; border-top: 1px solid var(--border);
}
.tree-node {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; min-block-size: 44px;
  background: var(--surface); border: 1px solid var(--border-subtle);
}
.tree-leaf { padding-left: 32px; }
.tree-branch > summary { cursor: pointer; list-style: none; }
.tree-branch > summary::-webkit-details-marker { display: none; }
.tree-branch > summary > svg { flex: none; color: var(--text-icon); transition: transform var(--speed); }
.tree-branch[open] > summary > svg { transform: rotate(90deg); }
.tree-branch > summary:hover { border-color: var(--border); }
.tree-branch > summary:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 2px; }

/* A person as a node: initials, name, the lines under it. */
.person-card { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 1; }
.person-card-text { display: flex; flex-direction: column; min-width: 0; }
.person-card-name { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.person-card-name strong { font-size: var(--fs-sm); font-weight: 600; color: var(--text-body); }
.person-card-line { font-size: var(--fs-xs); color: var(--text-muted); }
.person-card-note {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); color: var(--warn-text);
}
.person-card.is-self strong { color: var(--accent-text); }
.tree-node:has(.person-card.is-self) { border-color: var(--accent); }
.person-card.is-muted { opacity: .72; }
.org-board {
  display: flex; align-items: center; gap: 8px; margin: 0 0 10px;
  font-size: var(--fs-xs); font-weight: 700;
  color: var(--text-secondary);
}
@media print {
  .tree-branch > summary > svg { display: none; }
}

/* ==========================================================================
   RELEASE NOTES

   One card per version, and inside it the changes GROUPED BY KIND rather than
   listed in the order they happened. Somebody opening this page has one of
   two questions — "what can I do now" or "was that thing fixed" — and a group
   answers both by pointing at one block instead of asking them to read
   everything.

   The kind's colour is the palette's own badge tone: new is the accent, fixed
   is green, improved is blue, removed is muted. Nothing new to learn.
   ========================================================================== */

/* The summary line: version, date, and HOW MUCH IS FOLDED BEHIND IT. The
   count is what makes a closed row worth opening — "17 değişiklik" says there
   is something here; a bare version number says nothing. */
/* SATIRIN TASIYICISI AD, numara degil. Numara sabit genislikte solda durup
   siralamayi veriyor; ad okunacak sey oldugu icin buyuk; tarih ve sayi sagda,
   yolun disinda. */
.release-sum { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
/* A <summary> spreads its children apart, so the row has to claim the space
   between the version and the chevron — otherwise it sits at its content
   width and the date and count bunch up against the title instead of
   holding the right-hand edge. */
.disclosure > summary > .release-sum { flex: 1; min-width: 0; }
.release-version { flex: none; min-width: 4.5em; }
.release-name {
  font-size: var(--fs-md); font-weight: 700; color: var(--text-body);
  flex: 1; min-width: 0;
}
.release-sum-meta { display: flex; align-items: baseline; gap: 12px; margin-left: auto; }
.release-sum-count { font-size: var(--fs-xs); color: var(--text-muted); }

/* A SOFT RED WASH ON HOVER, so a foldable row announces that it is one.
   `color-mix` and not a literal: this tint IS the accent and has to move when
   the accent moves. 4% over white is the same "gentle nod, not a light show"
   the menu rows use — a row you can click should say so without shouting. */
.card .disclosure > summary:hover {
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}
.card .disclosure[open] > summary {
  border-bottom: 1px solid var(--border-subtle);
}

/* A folded version is a ROW, not a card: no shadow, no second frame, one line
   between it and the next. Twenty cards down a page is a stack of boxes;
   twenty rows is a list. */
.disclosure + .disclosure { border-top: 1px solid var(--border-subtle); }

/* ==========================================================================
   THE HERO'S MOVING LINE

   A drawn market line drifting across the top panel, and the loop is
   SEAMLESS: the tile's every component has an integer period, so its last
   column equals its first. Sliding the layer by exactly one tile width lands
   on an identical frame — no jump, no visible seam, no start and end.

   FOUR THINGS THIS HAD TO GET RIGHT:

   1. TRANSFORM, NOTHING ELSE. `transform` and `opacity` are the only two
      properties a browser animates on the compositor: the GPU slides an
      already-painted layer and the main thread never wakes. Animating
      `background-position` would have been one line and would repaint the
      panel sixty times a second to draw the same picture.

   2. THE TILE HAS NO GRADIENT IN IT. The old pattern faded left-to-right,
      which is exactly what a tile may not do — the fade would repeat and
      every seam would show. The fade is a mask on the wrapper instead, so
      the pattern is even and the wrapper decides where it dies.

   3. IT DIES BEFORE THE TEXT. The mask takes it to nothing well right of
      centre, and the eyebrow, title and description all sit left. Nothing a
      reader must read has anything moving behind it — the one hard rule
      decoration has.

   4. SLOW. 48 seconds for a full tile. At that speed no single frame reads
      as movement; the panel simply is not still. A drift you can watch is a
      drift you have to ignore, and people read numbers on these screens all
      day.
   ========================================================================== */
.hero-wave {
  position: absolute; inset: 0; z-index: -1;
  overflow: hidden; pointer-events: none; border-radius: inherit;
  -webkit-mask-image: linear-gradient(90deg, transparent 34%, #000 78%);
          mask-image: linear-gradient(90deg, transparent 34%, #000 78%);
}
.hero-wave::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0;
  /* One tile wider than the panel can ever be, so the trailing edge is never
     reached before the loop restarts. */
  width: calc(100% + 900px);
  background-color: var(--accent);
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='132' fill='none'%3E%3Cpath d='M0,80.7L10,81.3L20,81.6L30,81.8L40,81.8L50,81.7L60,81.4L70,81L80,80.6L90,80L100,79.4L110,78.7L120,78.1L130,77.4L140,76.7L150,76L160,75.3L170,74.7L180,74.1L190,73.6L200,73.1L210,72.6L220,72.1L230,71.7L240,71.3L250,70.9L260,70.5L270,70L280,69.6L290,69.1L300,68.5L310,67.8L320,67.1L330,66.2L340,65.3L350,64.2L360,63.1L370,61.7L380,60.3L390,58.7L400,57.1L410,55.3L420,53.4L430,51.4L440,49.3L450,47.2L460,45.1L470,42.9L480,40.8L490,38.7L500,36.6L510,34.6L520,32.8L530,31.1L540,29.5L550,28.2L560,27L570,26.1L580,25.4L590,25L600,24.8L610,24.9L620,25.3L630,26L640,26.9L650,28.1L660,29.5L670,31.2L680,33.1L690,35.2L700,37.5L710,40L720,42.6L730,45.2L740,48L750,50.8L760,53.6L770,56.4L780,59.1L790,61.8L800,64.3L810,66.8L820,69.1L830,71.2L840,73.2L850,74.9L860,76.5L870,77.9L880,79L890,80L900,80.7' stroke='%23e0362a' stroke-opacity='0.34' stroke-width='1.5'/%3E%3Cpath d='M0,96.8L10,95.5L20,94.1L30,92.8L40,91.5L50,90.2L60,89L70,87.8L80,86.6L90,85.5L100,84.4L110,83.4L120,82.4L130,81.5L140,80.7L150,80L160,79.3L170,78.7L180,78.2L190,77.8L200,77.4L210,77.2L220,77.1L230,77L240,77L250,77.2L260,77.4L270,77.7L280,78.1L290,78.6L300,79.2L310,79.8L320,80.6L330,81.4L340,82.2L350,83.2L360,84.2L370,85.3L380,86.4L390,87.6L400,88.8L410,90L420,91.3L430,92.6L440,93.9L450,95.2L460,96.5L470,97.9L480,99.2L490,100.5L500,101.8L510,103L520,104.2L530,105.4L540,106.5L550,107.6L560,108.6L570,109.6L580,110.5L590,111.3L600,112L610,112.7L620,113.3L630,113.8L640,114.2L650,114.6L660,114.8L670,114.9L680,115L690,115L700,114.8L710,114.6L720,114.3L730,113.9L740,113.4L750,112.8L760,112.2L770,111.4L780,110.6L790,109.8L800,108.8L810,107.8L820,106.7L830,105.6L840,104.4L850,103.2L860,102L870,100.7L880,99.4L890,98.1L900,96.8' stroke='%23e0362a' stroke-opacity='0.24' stroke-width='1.1'/%3E%3C/svg%3E");
  mask-repeat: repeat-x;
  mask-size: 900px 100%;
  animation: hero-drift 48s linear infinite;
}
@keyframes hero-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-900px, 0, 0); }
}
/* The only motion on a content screen, and it stops when the system asks. */
@media (prefers-reduced-motion: reduce) {
  .hero-wave::before { animation: none; }
}

/*
 * WHAT MOVES BEHIND A HEADING - the reader's choice, and all of it one
 * technique.
 *
 * A PERFECT LOOP IS A REPEATING TILE AND ONE `translateX`. The tile is one
 * tile wider than the panel can be and the animation walks it exactly one
 * tile's width, so the frame where it restarts is the frame it started on:
 * there is nothing to jump. Every curve's components have a period that
 * divides the tile exactly, which is what makes the seam invisible rather
 * than merely quick.
 *
 * ONLY `transform` IS ANIMATED. `background-position` would repaint on the
 * main thread every frame; a transform stays on the compositor and costs
 * the page nothing while somebody reads a table in front of it.
 *
 * THERE WAS A FOURTH, "isik", AND IT IS GONE. It was a wash of filled
 * colour and every other thing in this panel is a hairline - it read as a
 * stain rather than as a pattern, which is exactly what came back as
 * feedback. What replaced it stays in the same ink: 1.1-1.5px strokes at
 * 24-34%, the accent arriving through a mask.
 *
 * THE FADE STAYS ON THE PARENT in all of them: `.hero-wave` carries the
 * mask that dissolves the pattern before it reaches the title. A pattern
 * that runs under the words is the fault that mask was added for.
 */

/* -- duz: hicbir sey ------------------------------------------------- */
:root[data-pattern="plain"] .hero-wave { display: none; }

/*
 * -- derinlik: ayni egri, iki hizda -----------------------------------
 *
 * One curve drifting is a line. Two of them at different speeds is a
 * DISTANCE: the eye reads the slower one as further away, which is the
 * whole of what parallax is. Same tile, same ink, one extra layer - the
 * quietest way to add depth without adding anything.
 */
:root[data-pattern="depth"] .hero-wave::before { animation-duration: 74s; opacity: .55; }
:root[data-pattern="depth"] .hero-wave::after {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0;
  width: calc(100% + 900px);
  background-color: var(--accent);
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='132' fill='none'%3E%3Cpath d='M0,80.7L10,81.3L20,81.6L30,81.8L40,81.8L50,81.7L60,81.4L70,81L80,80.6L90,80L100,79.4L110,78.7L120,78.1L130,77.4L140,76.7L150,76L160,75.3L170,74.7L180,74.1L190,73.6L200,73.1L210,72.6L220,72.1L230,71.7L240,71.3L250,70.9L260,70.5L270,70L280,69.6L290,69.1L300,68.5L310,67.8L320,67.1L330,66.2L340,65.3L350,64.2L360,63.1L370,61.7L380,60.3L390,58.7L400,57.1L410,55.3L420,53.4L430,51.4L440,49.3L450,47.2L460,45.1L470,42.9L480,40.8L490,38.7L500,36.6L510,34.6L520,32.8L530,31.1L540,29.5L550,28.2L560,27L570,26.1L580,25.4L590,25L600,24.8L610,24.9L620,25.3L630,26L640,26.9L650,28.1L660,29.5L670,31.2L680,33.1L690,35.2L700,37.5L710,40L720,42.6L730,45.2L740,48L750,50.8L760,53.6L770,56.4L780,59.1L790,61.8L800,64.3L810,66.8L820,69.1L830,71.2L840,73.2L850,74.9L860,76.5L870,77.9L880,79L890,80L900,80.7' stroke='%23e0362a' stroke-opacity='0.34' stroke-width='1.5'/%3E%3Cpath d='M0,96.8L10,95.5L20,94.1L30,92.8L40,91.5L50,90.2L60,89L70,87.8L80,86.6L90,85.5L100,84.4L110,83.4L120,82.4L130,81.5L140,80.7L150,80L160,79.3L170,78.7L180,78.2L190,77.8L200,77.4L210,77.2L220,77.1L230,77L240,77L250,77.2L260,77.4L270,77.7L280,78.1L290,78.6L300,79.2L310,79.8L320,80.6L330,81.4L340,82.2L350,83.2L360,84.2L370,85.3L380,86.4L390,87.6L400,88.8L410,90L420,91.3L430,92.6L440,93.9L450,95.2L460,96.5L470,97.9L480,99.2L490,100.5L500,101.8L510,103L520,104.2L530,105.4L540,106.5L550,107.6L560,108.6L570,109.6L580,110.5L590,111.3L600,112L610,112.7L620,113.3L630,113.8L640,114.2L650,114.6L660,114.8L670,114.9L680,115L690,115L700,114.8L710,114.6L720,114.3L730,113.9L740,113.4L750,112.8L760,112.2L770,111.4L780,110.6L790,109.8L800,108.8L810,107.8L820,106.7L830,105.6L840,104.4L850,103.2L860,102L870,100.7L880,99.4L890,98.1L900,96.8' stroke='%23e0362a' stroke-opacity='0.24' stroke-width='1.1'/%3E%3C/svg%3E");
  mask-repeat: repeat-x;
  mask-size: 900px 100%;
  /* Half a tile along, so the two layers are never the same picture. */
  mask-position: 450px 0;
  animation: hero-drift 36s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  :root[data-pattern="depth"] .hero-wave::after { animation: none; }
}

/*
 * -- kontur: harita egrileri ------------------------------------------
 *
 * Five nested curves, the figure a contour map makes, drifting at half the
 * wave's speed. Every component's period divides the 900px tile, so all
 * five meet themselves exactly at the seam.
 */
:root[data-pattern="contour"] .hero-wave::before {
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='132' fill='none'%3E%3Cpath d='M0,26.0L10,27.1L20,28.2L30,29.3L40,30.3L50,31.3L60,32.2L70,33.0L80,33.8L90,34.5L100,35.1L110,35.6L120,36.1L130,36.4L140,36.6L150,36.7L160,36.8L170,36.7L180,36.6L190,36.3L200,36.0L210,35.7L220,35.2L230,34.8L240,34.2L250,33.7L260,33.1L270,32.6L280,32.0L290,31.4L300,30.8L310,30.3L320,29.8L330,29.3L340,28.9L350,28.4L360,28.1L370,27.7L380,27.4L390,27.1L400,26.9L410,26.7L420,26.5L430,26.3L440,26.2L450,26.0L460,25.8L470,25.7L480,25.5L490,25.3L500,25.1L510,24.9L520,24.6L530,24.3L540,23.9L550,23.6L560,23.1L570,22.7L580,22.2L590,21.7L600,21.2L610,20.6L620,20.0L630,19.4L640,18.9L650,18.3L660,17.8L670,17.2L680,16.8L690,16.3L700,16.0L710,15.7L720,15.4L730,15.3L740,15.2L750,15.3L760,15.4L770,15.6L780,15.9L790,16.4L800,16.9L810,17.5L820,18.2L830,19.0L840,19.8L850,20.7L860,21.7L870,22.7L880,23.8L890,24.9L900,26.0' stroke='%23000' stroke-opacity='0.34' stroke-width='1.5'/%3E%3Cpath d='M0,53.2L10,54.1L20,54.9L30,55.6L40,56.3L50,56.9L60,57.3L70,57.7L80,58.0L90,58.2L100,58.3L110,58.3L120,58.2L130,58.0L140,57.8L150,57.5L160,57.1L170,56.7L180,56.2L190,55.7L200,55.2L210,54.6L220,54.0L230,53.4L240,52.8L250,52.2L260,51.6L270,51.0L280,50.4L290,49.8L300,49.3L310,48.7L320,48.2L330,47.7L340,47.3L350,46.8L360,46.4L370,46.0L380,45.5L390,45.1L400,44.7L410,44.3L420,43.9L430,43.5L440,43.1L450,42.7L460,42.2L470,41.8L480,41.3L490,40.8L500,40.3L510,39.8L520,39.3L530,38.8L540,38.3L550,37.8L560,37.3L570,36.8L580,36.3L590,35.9L600,35.5L610,35.2L620,34.9L630,34.6L640,34.4L650,34.3L660,34.3L670,34.3L680,34.5L690,34.7L700,35.0L710,35.4L720,35.9L730,36.4L740,37.1L750,37.8L760,38.6L770,39.5L780,40.4L790,41.4L800,42.5L810,43.6L820,44.7L830,45.8L840,46.9L850,48.0L860,49.2L870,50.2L880,51.3L890,52.3L900,53.2' stroke='%23000' stroke-opacity='0.3' stroke-width='1.3'/%3E%3Cpath d='M0,80.5L10,80.9L20,81.1L30,81.3L40,81.3L50,81.2L60,81.1L70,80.8L80,80.5L90,80.0L100,79.5L110,79.0L120,78.4L130,77.7L140,77.0L150,76.3L160,75.5L170,74.8L180,74.0L190,73.3L200,72.5L210,71.8L220,71.1L230,70.4L240,69.8L250,69.2L260,68.6L270,68.0L280,67.5L290,66.9L300,66.4L310,66.0L320,65.5L330,65.1L340,64.6L350,64.2L360,63.7L370,63.3L380,62.9L390,62.4L400,62.0L410,61.5L420,61.0L430,60.5L440,60.0L450,59.5L460,58.9L470,58.4L480,57.9L490,57.3L500,56.8L510,56.3L520,55.9L530,55.5L540,55.1L550,54.7L560,54.5L570,54.2L580,54.1L590,54.0L600,54.1L610,54.2L620,54.4L630,54.7L640,55.1L650,55.6L660,56.2L670,56.9L680,57.7L690,58.6L700,59.5L710,60.5L720,61.6L730,62.8L740,64.0L750,65.3L760,66.5L770,67.8L780,69.1L790,70.4L800,71.6L810,72.8L820,74.0L830,75.1L840,76.1L850,77.1L860,78.0L870,78.8L880,79.4L890,80.0L900,80.5' stroke='%23000' stroke-opacity='0.27' stroke-width='1.2'/%3E%3Cpath d='M0,100.9L10,100.6L20,100.2L30,99.7L40,99.2L50,98.6L60,98.0L70,97.4L80,96.7L90,96.1L100,95.4L110,94.7L120,94.0L130,93.4L140,92.7L150,92.0L160,91.4L170,90.8L180,90.2L190,89.6L200,89.1L210,88.5L220,88.0L230,87.5L240,87.1L250,86.6L260,86.2L270,85.7L280,85.3L290,84.9L300,84.5L310,84.1L320,83.7L330,83.3L340,82.9L350,82.5L360,82.1L370,81.7L380,81.3L390,80.9L400,80.5L410,80.2L420,79.8L430,79.5L440,79.2L450,78.9L460,78.7L470,78.5L480,78.3L490,78.2L500,78.2L510,78.2L520,78.3L530,78.4L540,78.7L550,79.0L560,79.3L570,79.8L580,80.3L590,80.9L600,81.6L610,82.3L620,83.1L630,84.0L640,84.9L650,85.9L660,86.9L670,87.9L680,88.9L690,90.0L700,91.1L710,92.1L720,93.2L730,94.2L740,95.1L750,96.1L760,96.9L770,97.8L780,98.5L790,99.2L800,99.8L810,100.3L820,100.7L830,101.0L840,101.3L850,101.4L860,101.5L870,101.5L880,101.4L890,101.2L900,100.9' stroke='%23000' stroke-opacity='0.24' stroke-width='1.1'/%3E%3Cpath d='M0,116.0L10,115.4L20,114.9L30,114.3L40,113.8L50,113.2L60,112.7L70,112.1L80,111.6L90,111.1L100,110.6L110,110.1L120,109.7L130,109.2L140,108.8L150,108.4L160,108.0L170,107.7L180,107.3L190,107.0L200,106.7L210,106.4L220,106.0L230,105.8L240,105.5L250,105.2L260,104.9L270,104.6L280,104.4L290,104.1L300,103.8L310,103.6L320,103.3L330,103.1L340,102.9L350,102.7L360,102.5L370,102.3L380,102.2L390,102.1L400,102.0L410,102.0L420,102.0L430,102.0L440,102.1L450,102.2L460,102.4L470,102.7L480,103.0L490,103.3L500,103.7L510,104.2L520,104.7L530,105.2L540,105.8L550,106.5L560,107.2L570,107.9L580,108.6L590,109.4L600,110.2L610,111.0L620,111.8L630,112.6L640,113.4L650,114.1L660,114.9L670,115.6L680,116.2L690,116.8L700,117.4L710,117.9L720,118.4L730,118.8L740,119.1L750,119.4L760,119.6L770,119.7L780,119.7L790,119.7L800,119.6L810,119.5L820,119.3L830,119.0L840,118.7L850,118.3L860,117.9L870,117.5L880,117.0L890,116.5L900,116.0' stroke='%23000' stroke-opacity='0.21' stroke-width='1.1'/%3E%3C/svg%3E");
  animation-duration: 96s;
}


/* ==========================================================================
   EMPHASIS INSIDE A RELEASE NOTE

   Sixty sentences of even weight is sixty sentences nobody scans. The SUBJECT
   of each line — the screen, the button, the thing that broke — carries the
   accent, so the eye finds the one it came for without reading the rest.

   `--accent-text` and NOT `--accent`: this is text, and the vivid brand tone
   does not clear 4.5:1 on any of the three grounds text is read on (§6.3).
   The gate measures this exact pair on every run.
   ========================================================================== */
.hl { color: var(--accent-text); font-weight: 700; }

/* Which patch numbers a release entry covers. A quiet line under the
   headline: it answers a question only the person running one of those
   numbers is asking. */
/* Yil ayraci: yalnizca yil degistiginde ciziliyor, yani bugun hic. */
.release-year {
  padding: 14px 22px 6px;
  font-size: var(--fs-xs); font-weight: 800;
  color: var(--text-muted);
  border-top: 1px solid var(--border-subtle);
}

.release-patches {
  margin-top: 8px;
  font-size: var(--fs-xs); color: var(--text-muted);
}
/* The number as a tag, not as loose grey digits. */
.release-version {
  font-variant-numeric: tabular-nums; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0;
  color: var(--text-secondary);
  padding: 2px 7px; border: 1px solid var(--border); background: var(--surface);
  text-align: center;
}
.disclosure.is-current .release-version { color: var(--accent-text); border-color: var(--accent); background: var(--accent-tint); }
.release-name .badge { margin-left: 8px; vertical-align: 2px; }
.release-date { font-size: var(--fs-xs); color: var(--text-muted); min-width: 8.5em; text-align: right; }
/* One count per kind, in the kind's colour: "6 yeni · 3 düzeltme". */
.release-kinds { display: inline-flex; gap: 10px; }
.release-kind { font-size: var(--fs-xs); font-weight: 600; color: var(--text-secondary); white-space: nowrap; }
.release-kind::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 5px; vertical-align: 1px; background: var(--text-muted); }
.release-kind-added::before { background: var(--accent); }
.release-kind-fixed::before { background: var(--ok); }
.release-kind-changed::before { background: var(--info); }
.release-list code {
  font-family: var(--font-mono); font-size: .92em;
  padding: 1px 5px; background: var(--surface-sunken); border: 1px solid var(--border-subtle);
}
/* The version in use, at the right of the page head. */
/* Its own ground, so the page head's drifting line passes behind the words. */
.release-now {
  display: grid; justify-items: end; gap: 2px; text-align: right; position: relative; z-index: 1;
  padding: 8px 12px; background: var(--surface); border: 1px solid var(--border-subtle);
}
.release-now-label { font-size: var(--fs-2xs); font-weight: 800; color: var(--text-muted); }
.release-now-version { font-variant-numeric: tabular-nums; font-size: var(--fs-lg); color: var(--accent-text); }
.release-now-meta { font-size: var(--fs-xs); color: var(--text-secondary); }
@media (max-width: 720px) {
  .release-now { justify-items: start; text-align: left; }
  .release-kinds { display: none; }
}
.release-headline {
  color: var(--text-secondary); font-size: var(--fs-sm); line-height: 1.6;
  max-width: 720px;
}

/* Two columns where there is room, one where there is not. The groups are
   short lists, and a single 900px-wide column of four-word lines reads as a
   page nobody finished designing. */
.release-groups {
  margin-top: 18px;
  display: grid; gap: 18px 28px;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
.release-group-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.release-count {
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); color: var(--text-muted);
}
/* The marker is the badge above, so the list needs none of its own — a bullet
   beside a coloured label is two markers for one idea. */
.release-list { list-style: none; display: grid; gap: 9px; }
.release-list li {
  position: relative; padding-left: 15px;
  font-size: var(--fs-sm); line-height: 1.6; color: var(--text-body);
}
.release-list li::before {
  content: ""; position: absolute; left: 0; top: 9px;
  width: 5px; height: 5px; background: var(--border-input);
}
.card + .card { margin-top: var(--rhythm); }

/* Üst şeritteki kişi bloğu artık kendi hesap sayfasına giden bağlantı.
   Çıkış formu bu bağlantının DIŞINDA kalır — form-in-anchor geçersiz HTML. */
.topbar-user-link { display: flex; align-items: center; gap: 14px; color: inherit; text-decoration: none; padding: 4px 6px; }
.topbar-user-link:hover { background: var(--surface-sunken); }
.topbar-user-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }

/* -- radyo grubu ---------------------------------------------------------- */

/* Every option visible, and the whole row is the target: a 13px circle is a
   hard thing to hit and there is no reason to make anyone aim at it. */
.radio-group { display: grid; gap: 8px; border: 0; padding: 0; margin: 0; }
/* A ROW OF CHOICES RATHER THAN A COLUMN OF THEM. Five interface colours
   as five full-width rows is a screen you scroll to answer one question;
   as a wrapping row it is one glance. Only for options short enough to
   read in a line - a choice that needs a sentence keeps the column. */
.radio-options { display: grid; gap: 8px; }
.radio-group-grid .radio-options { grid-template-columns: repeat(auto-fit, minmax(156px, 1fr)); }
.radio-group .label { margin-bottom: 2px; }
.radio-option {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.radio-option:hover { border-color: var(--border-hover); background: var(--surface-hover); }
.radio-option input { margin-top: 2px; flex: none; accent-color: var(--accent-solid); }
/* The chosen row carries the accent bar the rest of the design system uses
   for "this one", so the state is readable without relying on the dot alone. */
.radio-option:has(input:checked) {
  border-color: var(--accent);
  background: var(--surface-sunken);
}
.radio-option:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: -3px; }
.radio-text { display: grid; gap: 2px; min-width: 0; }
.radio-text strong { font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
.radio-text em { font-style: normal; font-size: var(--fs-xs); color: var(--text-secondary); line-height: 1.5; }

/* A question and its answers on one row (components.ts choiceRow). The
   answers keep one width, so every "Evet" of a questionnaire stands under the
   one above it; below 620px they drop under the sentence. */
.choice-row {
  display: flex; align-items: center; gap: 10px 20px; flex-wrap: wrap;
  border: 0; margin: 0; padding: 12px 0;
}
.choice-row + .choice-row { border-top: 1px solid var(--border-subtle); }
.choice-question { flex: 1 1 320px; min-width: 0; font-size: var(--fs-sm); color: var(--text-body); line-height: 1.5; }
.choice-options { display: flex; gap: 8px; flex: none; }
.choice-option {
  display: inline-flex; align-items: center; gap: 8px;
  min-width: 104px; height: var(--control-h-sm); padding: 0 14px;
  border: 1px solid var(--border); background: var(--surface);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-body);
  cursor: pointer; transition: border-color var(--speed), background var(--speed);
}
.choice-option:hover { border-color: var(--border-hover); background: var(--surface-hover); }
.choice-option input { margin: 0; flex: none; accent-color: var(--accent-solid); }
.choice-option:has(input:checked) { border-color: var(--accent); background: var(--surface-sunken); }
.choice-option:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: -3px; }
.choice-row .field-error { flex-basis: 100%; }
@media (max-width: 620px) {
  .choice-options { width: 100%; }
  .choice-option { flex: 1 1 0; }
}

/* A form that sits among buttons in a row takes no line of its own. */
.inline-form { display: contents; }

/* Akit's request form: the required fields beside the form, each a link to
   its box. Done ones are ticked and quiet; a refused one is red. */
.request-checklist li { padding: 6px 0; }
.request-checklist a { color: var(--text-secondary); }
.request-checklist li.is-done a { color: var(--text-muted); }
.request-checklist li.is-problem a { color: var(--error-text); font-weight: 600; }

/* The preview, not a decoration: a page, a card on it, and the red bar this
   application puts on top of a card. Three shapes is enough to recognise. */
.theme-chip {
  flex: none; width: 52px; height: 36px;
  border: 1px solid var(--border);
  display: grid; place-items: center;
}
.theme-chip i { display: block; width: 32px; height: 18px; border-top: 3px solid var(--accent); }
.theme-chip-light { background: var(--chip-light-page); }
.theme-chip-light i { background: var(--chip-light-card); }
.theme-chip-dark { background: var(--chip-dark-page); }
.theme-chip-dark i { background: var(--chip-dark-card); }
/* Both at once, split on the diagonal - the shape of "whichever the machine
   is". */
/*
 * THE INTERFACE-COLOUR SWATCH.
 *
 * It carries `data-accent` itself, so the preset block re-scopes the tokens
 * inside it and the chip draws with the preset's OWN rail and fill. No hex is
 * written here; the swatch cannot disagree with the thing it previews. The
 * Stablex one carries no attribute at all and inherits the brand palette.
 */
.accent-chip {
  flex: none; width: 52px; height: 36px;
  display: grid; place-items: center;
  background: var(--sidebar-bg);
  border: 1px solid var(--border);
}
.accent-chip i { display: block; width: 26px; height: 14px; background: var(--accent-solid); }

.theme-chip-system {
  background: linear-gradient(135deg, var(--chip-light-page) 0 50%, var(--chip-dark-page) 50% 100%);
}
.theme-chip-system i {
  background: linear-gradient(135deg, var(--chip-light-card) 0 50%, var(--chip-dark-card) 50% 100%);
}

/* SCRIPT PRESENT: the choice takes effect as it is made, so a Save button
   would be a button that has already happened. Blocked: it is the only way,
   and it is right there. */
.js [data-pref-save] { display: none; }

/* -- page to page ---------------------------------------------------------- */

/*
 * EVERY LINK IS A FULL PAGE LOAD, and it looked like one: the whole window
 * blanked and redrew, rail and top strip included, although neither had
 * changed. The browser's own cross-document transition keeps those two
 * standing still (named, no animation) and only cross-fades what is under
 * them. No script: a browser without it simply navigates as before, and a
 * reader who asked for less motion - here or in the system - gets none.
 */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
.sidebar { view-transition-name: hub-rail; }
.topbar { view-transition-name: hub-topbar; }
::view-transition-group(hub-rail), ::view-transition-group(hub-topbar),
::view-transition-old(hub-rail), ::view-transition-new(hub-rail),
::view-transition-old(hub-topbar), ::view-transition-new(hub-topbar) { animation: none; }
::view-transition-old(hub-rail), ::view-transition-old(hub-topbar) { display: none; }
/*
 * NO CROSS-FADE OF THE PAGE ITSELF (2026-10-29). The old page faded out over
 * 120ms while the new one faded in over 180ms, so for a moment both were on
 * the screen at once: picking a card on the desk showed the board's summary
 * through the card ("panel aşağı ışınlanıyor", recorded frame by frame). The
 * new page now simply replaces the old one - the browser keeps the old one
 * painted until the new one is ready, so nothing blanks - and an arrival at
 * ANOTHER screen still fades in by itself (`.main[data-enter]`, the reader's
 * own setting), from the page's background, never through the old content.
 */
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
:root[data-motion="off"]::view-transition-group(*),
:root[data-motion="off"]::view-transition-old(*),
:root[data-motion="off"]::view-transition-new(*) { animation: none !important; }

/* -- choices with a picture (components.ts radioGroup + prefPreview) ------ */

/* The options sit in their own grid (.radio-options), under the hint. */
.radio-group-preview .radio-options { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.radio-option.has-preview { align-items: center; padding: 10px 10px 10px 13px; }
.radio-option.has-preview .radio-text { flex: 1; }
.radio-preview { display: flex; flex: none; margin-left: auto; }

/* THUMBNAILS: picture on top, dot and name under it, side by side at a fixed
   width. The pointer moves a thumbnail's width between choices. */
.radio-group-tiles .radio-options { display: flex; flex-wrap: wrap; gap: 8px; }
.radio-group-tiles .radio-option.has-preview {
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "pv pv" "in tx";
  align-items: center; gap: 7px 6px;
  width: 118px; padding: 7px 8px 8px;
}
.radio-group-tiles .radio-preview { grid-area: pv; margin: 0; justify-content: center; }
.radio-group-tiles .radio-option input { grid-area: in; margin: 0; }
.radio-group-tiles .radio-text { grid-area: tx; }
.radio-group-tiles .radio-text strong { font-size: var(--fs-xs); line-height: 1.3; }
.radio-group-tiles .mini-ui, .radio-group-tiles .mini-ui-split,
.radio-group-tiles .mini-font, .radio-group-tiles .mini-hero, .radio-group-tiles .mini-arrive { width: 100px; height: 60px; }

/* A settings list (components.ts settingRows). */
.setting-row {
  display: grid; grid-template-columns: minmax(200px, 260px) minmax(0, 1fr);
  gap: 12px 32px; padding: 18px 22px; align-items: start;
}
.setting-row + .setting-row { border-top: 1px solid var(--border-subtle); }
.setting-row-head h3 { margin: 0 0 4px; font-size: var(--fs-md); font-weight: 700; color: var(--text-body); }
.setting-row-head p { margin: 0; font-size: var(--fs-xs); line-height: 1.55; color: var(--text-secondary); }
@media (max-width: 820px) {
  .setting-row { grid-template-columns: minmax(0, 1fr); padding: 16px; }
}

/* A screen in miniature: rail, top strip, two cards, the first one wearing
   the accent bar every card here wears. */
.mini-ui {
  position: relative; flex: none; width: 92px; height: 58px;
  display: grid; grid-template-columns: 20px 1fr;
  border: 1px solid var(--border); overflow: hidden;
  background: var(--surface-sunken); color: var(--text-secondary);
}
.mini-ui-rail { background: var(--sidebar-bg); display: grid; align-content: start; gap: 4px; padding: 9px 4px; box-shadow: inset -1px 0 rgba(255, 255, 255, .12); }
.mini-ui-rail i { display: block; height: 3px; background: rgba(255, 255, 255, .45); }
.mini-ui-rail i:first-child { background: rgba(255, 255, 255, .9); }
.mini-ui-main { display: grid; grid-template-rows: 8px 1fr 1fr; gap: 4px; padding: 0 5px 5px; min-width: 0; }
.mini-ui-top { margin: 0 -5px; background: var(--surface); border-bottom: 1px solid color-mix(in srgb, currentColor 22%, transparent); }
.mini-ui-card { background: var(--surface); display: grid; align-content: center; gap: 3px; padding: 0 5px; }
.mini-ui-card.is-lead { border-top: 2px solid var(--accent); }
.mini-ui-card i { display: block; height: 2px; background: currentColor; opacity: .35; }
.mini-ui-card i + i { width: 58%; }
/* The two themes are drawn with the fixed chip tokens: "Koyu" is dark on a
   light screen and "Açık" is light on a dark one. */
.mini-ui-light { background: var(--chip-light-page); color: var(--chip-dark-card); }
.mini-ui-light .mini-ui-top, .mini-ui-light .mini-ui-card { background: var(--chip-light-card); }
.mini-ui-dark { background: var(--chip-dark-page); color: var(--chip-light-card); }
.mini-ui-dark .mini-ui-top, .mini-ui-dark .mini-ui-card { background: var(--chip-dark-card); }
/* "Sistem": both at once, split on the diagonal. */
.mini-ui-split { position: relative; flex: none; width: 92px; height: 58px; }
.mini-ui-split > .mini-ui { position: absolute; inset: 0; }
.mini-ui-split > .mini-ui-dark { clip-path: polygon(100% 0, 100% 100%, 0 100%); }

/* A typeface: its own letters, in its own face (data-font re-scopes the
   token on this element). */
.mini-font {
  flex: none; width: 92px; height: 58px;
  display: grid; place-items: center; align-content: center; gap: 3px;
  border: 1px solid var(--border); background: var(--surface-sunken);
  font-family: var(--font-sans); color: var(--text-body);
}
.mini-font b { font-size: 24px; line-height: 1; font-weight: 700; }
.mini-font small { font-size: 12px; color: var(--text-secondary); }

/* A page head: the red bar, a title, and the pattern behind it. */
.mini-hero {
  position: relative; flex: none; width: 92px; height: 58px;
  border: 1px solid var(--border); background: var(--surface); overflow: hidden;
}
.mini-hero::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--accent); z-index: 1; }
.mini-hero svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.mini-hero path { fill: none; stroke: var(--accent); stroke-width: 1.3; opacity: .6; vector-effect: non-scaling-stroke; }
.mini-hero path.o-mid { opacity: .4; }
.mini-hero path.o-soft { opacity: .25; }
.mini-hero i { position: absolute; left: 10px; top: 11px; width: 42px; height: 5px; background: var(--text-body); opacity: .8; }
.mini-hero i + i { top: 21px; width: 58px; height: 3px; opacity: .3; }
.mini-hero-moving svg { animation: mini-drift 5s ease-in-out infinite alternate; }
.mini-hero-still path { stroke: var(--text-muted); }
@keyframes mini-drift { from { transform: translateX(-8px); } to { transform: translateX(8px); } }
@media (prefers-reduced-motion: reduce) { .mini-hero-moving svg { animation: none; } }

/* How a page arrives, as three frames left to right. */
.mini-arrive {
  flex: none; width: 92px; height: 58px;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; padding: 10px 7px;
  align-items: start; border: 1px solid var(--border); background: var(--surface-sunken);
}
.mini-arrive i { display: block; height: 30px; background: var(--surface); border-top: 2px solid var(--accent); box-shadow: inset 0 0 0 1px var(--border); }
.mini-arrive-fade i:nth-child(1) { opacity: .2; }
.mini-arrive-fade i:nth-child(2) { opacity: .55; }
.mini-arrive-rise i:nth-child(1) { opacity: .2; transform: translateY(9px); }
.mini-arrive-rise i:nth-child(2) { opacity: .55; transform: translateY(4px); }
/* The same for a chooser that applies itself on change (app.js,
   `data-autosubmit`). Without script the button stays and does the job. */
/* `data-keep-visible`: the same button also submits a text box (a search), so
   it stays - the select still applies itself through it. */
.js [data-autosubmit-button]:not([data-keep-visible]) { display: none; }
[data-pref-status] {
  font-size: var(--fs-xs); font-weight: 700; color: var(--ok-text);
  opacity: 0; transition: opacity var(--speed);
}
[data-pref-status].is-on { opacity: 1; }

/* The bubble and its count sit together; without this the badge lands on the
   next line the moment the number is two digits. */
.topbar-messages { display: inline-flex; align-items: center; gap: 6px; padding-inline: 10px; }

/* -- kisi secici ---------------------------------------------------------- */

/*
 * SAG PANELDE, TAM YUKSEKLIKTE - ortada duran iki kart degil.
 *
 * Slack ve Teams bu ekrani sag panelde ciziyor, ray yerinde kalarak; hicbiri
 * tam sayfa bir yere gitmiyor. Liste kendi icinde kayiyor, dugme altta sabit.
 */
/*
 * SECICI BIR EKRAN DEGIL, BIR PANEL.
 *
 * Once bu tam genislikte bir sayfaydi: isimler kocaman bos bir alanin
 * solunda, arama kutusu sag ust kosede — suzdugu listeden yarim ekran
 * uzakta — ve "ac" dugmesi ekranin en dibinde, oteki her seyden ayri.
 * Bildirilen hali: "ortada havada".
 *
 * Discord'un "arkadas sec" kutusu bir kip penceresi; kip penceresinin
 * GEOMETRISI burada makinesi olmadan da alinabiliyor: sinirli genislik,
 * kendi zemini, kendi cercevesi, ve her sey icinde okuma sirasinda.
 * Kip penceresinin kendisi alinmiyor — betiksiz calismasi gerekiyor ve
 * bu iki gercek adres, iki gercek form.
 */
/* Zemin bir flex kabi: panel onun yuksekligini asamiyor, dolayisiyla
   kayan sey LISTE oluyor, sayfa degil. Tasma buradan geliyordu. */
.pick-ground {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column;
  padding: 28px 24px;
}
.pick {
  display: flex; flex-direction: column;
  width: 100%; max-width: 560px; margin: 0 auto;
  max-height: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}
.pick-head {
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 14px 22px; border-bottom: 1px solid var(--border);
}
.pick-tabs { display: flex; gap: 4px; }
.pick-tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; font-size: var(--fs-sm); font-weight: 700;
  color: var(--text-secondary);
  border-bottom: var(--accent-bar) solid transparent;
}
.pick-tab:hover { color: var(--text-body); }
.pick-tab[aria-current="page"] { color: var(--accent-text); border-bottom-color: var(--accent); }
/*
 * ARAMA VE GRUP ADI TEK SATIRDA.
 *
 * Alt alta olduklarinda panel goruntuden tasiyor ve "Grubu ac" dugmesi
 * ekranin disinda kaliyordu — bildirilen hali. Ikisi esit paya bolunuyor:
 * biri buyuyup otekini eziyorsa satir esit degildir.
 */
/*
 * `.pick-bar`, NOT `.pick-row` - and the reason was measured.
 *
 * The same class name was used again further down for each person in the
 * list, and at equal specificity the later rule won for BOTH elements: this
 * bar became `display: flex`, so the grid above never applied and the two
 * boxes sized to their own content. Before the rename the bar measured 558px,
 * the search 248px and the group name 177px - neither equal nor filling the
 * row, which is the exact state the comment above says was fixed. Every
 * person row also inherited this bar's bottom border.
 */
/* 22px on the sides, like the rows and the foot below it: at 16px the search
   box began six pixels left of every checkbox and of the "Grubu ac" button. */
.pick-bar {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  padding: 12px 22px;
  border-bottom: 1px solid var(--border-subtle);
}
/* Tek giris varken (kisi secici) satirin tamamini alsin. */
.pick-bar:not(:has(.pick-name)) { grid-template-columns: 1fr; }
/*
 * THE SHARED SEARCH ROW — `searchBar()` in ui/components.ts.
 *
 * `.pick-search` below is the same shape and predates it, but it is scoped
 * inside the person picker and carries that panel's smaller control height.
 * This one is the general case: a box that takes the line and a button that
 * takes what it needs.
 */
.search-bar { display: flex; align-items: center; gap: 8px; min-width: 0; }
.search-bar > .field { flex: 1; min-width: 0; margin: 0; }
.search-bar > .btn { flex: none; }

/*
 * TWO BUTTONS THAT SHARE A LINE EVENLY — an add and its matching remove, a
 * confirm and its cancel. Equal columns rather than `flex`, because a pair
 * whose widths follow their labels reads as one important button and one
 * afterthought, and these are a pair precisely because neither is.
 *
 * THE LABELS WRAP INSTEAD OF BEING CUT. "Görünenlerin tümünü çıkar (74)" in a
 * half-width column is wider than the column, and `white-space: nowrap` on
 * `.btn` clipped it mid-word.
 */
.btn-split { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.btn-split > .btn {
  width: 100%; min-width: 0; height: auto; min-height: var(--control-h);
  padding: 6px 12px;
  white-space: normal; text-align: left; line-height: 1.3;
}
@media (max-width: 520px) { .btn-split { grid-template-columns: minmax(0, 1fr); } }

.pick-search { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pick-search .field { flex: 1; margin: 0; min-width: 0; }
.pick-name { min-width: 0; }
.pick-name .field { margin: 0; }

.pick-form { display: flex; flex-direction: column; min-height: 0; flex: 1; }

.pick-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 8px 0; }
/* NO BROWSER INDENT. `list-style: none` removes the bullet but not the 40px
   the browser reserves for it: measured, each person row was 518px inside a
   558px panel, so every checkbox stood 40px right of the search box above. */
.pick-list { list-style: none; padding-left: 0; }
.pick-row {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 22px; cursor: pointer;
  transition: background var(--speed);
}
.pick-row:hover { background: var(--surface-hover); }
/* Secili satir kendini soyluyor: kutucuk tek isaret degil. */
.pick-row:has(input:checked) { background: var(--surface-sunken); }
.pick-row input { flex: none; accent-color: var(--accent-solid); }
.pick-main { display: grid; gap: 1px; min-width: 0; }
.pick-main strong { font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
.pick-main em { font-style: normal; font-size: var(--fs-2xs); color: var(--text-muted); }
.pick-foot {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 22px; border-top: 1px solid var(--border); background: var(--surface);
}

/* -- tema dugmesi --------------------------------------------------------- */

/*
 * ONE BUTTON, TWO ICONS, AND CSS PICKS.
 *
 * The button offers the theme you are NOT in, so the icon has to follow what
 * is on the screen rather than what is in the database -- and only CSS knows
 * that, because "system" resolves in the browser. Both icons ship; the rules
 * below hide one. The consequence worth having: with the script blocked the
 * icon is still correct, and when the preferences screen changes the
 * attribute the icon changes with it, with nothing to keep in step.
 */
.theme-toggle { display: flex; align-items: center; }
.theme-toggle-btn { padding-inline: 10px; }
.theme-ico { display: none; }
/* Standing in the light: offer the moon. */
.theme-ico-dark { display: block; }
:root[data-theme="dark"] .theme-ico-dark { display: none; }
:root[data-theme="dark"] .theme-ico-light { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .theme-ico-dark { display: none; }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .theme-ico-light { display: block; }
}

/* ==========================================================================
   MESAJLASMA: iki panel

   The rail here REPLACES the application's sidebar rather than sitting beside
   it, which is why this screen has a layout of its own (`railShell`). The
   list is the navigation; there is nothing else to navigate to.

   THE SCROLL CHAIN IS THE WHOLE TRICK, and `min-height: 0` on every step of
   it is what makes it work. A flex or grid child refuses to shrink below its
   content by default, so without it the PAGE scrolls instead of the
   transcript - and the symptom is not "the layout is wrong", it is "the
   compose box disappears once there are enough messages".
   ========================================================================== */

.shell-fixed { height: 100vh; min-height: 0; overflow: hidden; }
.main-col-plain { background-image: none; }
/* The content column is a flex column; the page has to be allowed to grow
   into it AND to shrink below its content, or the composer walks off the
   bottom of the screen as soon as there are enough messages. */
.main-flush { padding: 0; max-width: none; min-height: 0; flex: 1; display: flex; }
.main-flush > .chat { flex: 1; min-height: 0; }

.msgrail {
  display: flex; flex-direction: column; min-height: 0;
  background: var(--surface-sunken);
  border-right: 1px solid var(--border);
  overflow: hidden;
}
/*
 * MESAJ RAYININ MARKA BLOGU.
 *
 * Kirmizi rayla ayni yer ve ayni olcu (dolgu ve genislik yukaridaki ortak
 * kuraldan geliyor), ama zemin acik oldugu icin ayirici cizgiler beyaz
 * alfa degil normal kenar jetonu.
 *
 * ISARET SIYAH. Dosya tek renk (#f9faf9, beyaza yakin) ve kirmizi ray icin
 * cizilmis; bu ray acik oldugu icin oldugu gibi kullanilamaz. brightness(0)
 * onu siyaha ceviriyor — ikinci bir dosya, ikinci bir adres ve ikinci bir
 * onbellek damgasi olmadan. KOYU TEMADA filtre kalkiyor: ray o zaman koyu,
 * ve siyah bir isaret gorunmezdi. Ucuncu blok, tema secimi "sistem" iken
 * isletim sistemini takip etmek icin — theme-ico ile ayni kalip.
 */
/* Yalnizca FARK OLAN: dolgu ve olcu .sidebar-brand'den geliyor, burada
   sadece acik zemine ait renkler var. */
.msgrail-brand {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.msgrail-brand img { filter: brightness(0); }
/* Serit de .sidebar-brand span'den geliyor; burada yalniz cizgiler ve
   yazi rengi acik zemine cevriliyor. */
.msgrail-brand span {
  border-top: 1px solid var(--border-subtle);
  border-bottom: 0;
  color: var(--text-secondary);
}
:root[data-theme="dark"] .msgrail-brand img { filter: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .msgrail-brand img { filter: none; }
}

/*
 * ARAMA CUBUGU — rayin basinda, listenin hemen ustunde.
 *
 * Discord'un "birini bul ya da yeni bir konusma baslat" cubugu ayni yerde.
 * Bir GET formu oldugu icin betiksiz de calisiyor: yazip Enter'a basmak
 * kisi seciciye o aramayla gidiyor.
 */
.msgrail-find {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-subtle);
}
.msgrail-find .field { flex: 1; margin: 0; min-width: 0; }

/*
 * BOLUM BASLIGI VE TEK BIR ARTI.
 *
 * Once burada dolgulu kirmizi bir dugme vardi — rayin icindeki en yuksek
 * sesli sey, ve yaninda ust seritte zaten yazan bir kelime. Kucuk, sessiz
 * ve tek tiklamalik olan dogru olani.
 */
.msgrail-section {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px 6px;
}
.msgrail-section span {
  flex: 1; min-width: 0;
  font-size: var(--fs-xs); font-weight: 800;
  color: var(--text-muted);
}

/* Marka blogunun altindaki serit burada "hub'a don" yerine geciyor:
   baglantinin kendisi zaten "/" adresine gidiyor, ikinci bir satir ayni
   yere giden iki bagi 40 piksel arayla dizmek olurdu. */
.msgrail-brand span {
  display: flex; align-items: center; gap: 6px;
}
.msgrail-brand:hover span { color: var(--text-body); }
.msgrail-list { flex: 1; min-height: 0; overflow-y: auto; }

/*
 * IKI SATIR, VE OLCULER TAHMIN DEGIL.
 *
 * Telegram Web'in kendi stil dosyasindan: iki satirli satir 72px, avatar 48px,
 * yazi avatari gececek kadar iceriden basliyor. WhatsApp, Telegram ve Teams bu
 * sekli kullaniyor; Slack ve Discord onizlemesiz tek satir kullaniyor, ama o
 * bir ODALAR listesi icin dogru - burasi KISILER listesi ve ikinci satir zaten
 * ona bakmanin sebebi.
 */
.msgrail-row {
  display: flex; align-items: center; gap: 12px;
  min-height: 72px;
  padding: 10px 14px;
  position: relative;
  border-bottom: 1px solid var(--border-subtle);
  transition: background var(--speed);
}
.msgrail-top, .msgrail-bottom {
  display: flex; align-items: baseline; gap: 8px; min-width: 0;
}
.msgrail-time { font-size: var(--fs-2xs); color: var(--text-muted); margin-left: auto; flex: none; }
.msgrail-preview {
  font-size: var(--fs-xs); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  flex: 1; min-width: 0;
}
/* Cevrimici noktasi avatarin kosesinde - satirda ikinci bir sutun acmadan. */
.msgrail-dot {
  position: absolute; left: 46px; bottom: 14px;
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--surface-sunken);
  background: var(--text-icon);
}
.msgrail-dot.presence-online { background: var(--ok-text); }
.msgrail-dot.presence-away { background: var(--warn-text); }
.msgrail-none { padding: 14px; font-size: var(--fs-xs); color: var(--text-muted); }
.msgrail-row:hover { background: var(--surface-hover); }
.msgrail-row[aria-current="page"] {
  background: var(--surface);
  border-left: var(--accent-bar) solid var(--accent);
  padding-left: calc(14px - var(--accent-bar));
}
.msgrail-main { display: grid; gap: 3px; min-width: 0; flex: 1; }
.msgrail-name {
  font-size: var(--fs-sm); font-weight: 700; color: var(--text-body);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.msgrail-note {
  font-size: var(--fs-2xs); color: var(--text-muted);
  display: flex; align-items: center; gap: 6px;
}

/* -- sag panel ------------------------------------------------------------ */

.chat { display: grid; grid-template-columns: minmax(0, 1fr); height: 100%; min-height: 0; }
.chat-with-info { grid-template-columns: minmax(0, 1fr) 300px; }

/*
 * NEWEST AT THE BOTTOM, AND THE PAGE OPENS THERE, WITH NO SCRIPT.
 *
 * A `column-reverse` container starts scrolled to its own bottom, so the list
 * is handed over NEWEST FIRST and the browser puts it the right way up and in
 * the right place. That only works if the bubbles are direct children of the
 * scrolling box - wrapped in an inner <ul> the reversal applies to the
 * wrapper, which is one element, and the messages come out backwards. They
 * did, once, and it is why the list element IS the scroller here.
 */
.chat-stream {
  display: flex; flex-direction: column-reverse;
  gap: 12px;
  overflow-y: auto; min-height: 0; flex: 1;
  list-style: none;
  padding: 18px 22px;
}
/* The bubbles keep their own width from .msg; the list gap does the rest.
   `align-items: flex-start` is what makes a side possible at all: in a
   column flex the default stretches every child to full width, and then
   `margin-left: auto` has nothing left to push against. */
.chat-stream { align-items: flex-start; }
.chat-stream .msg { margin: 0; }
.chat-stream .msg-mine { align-self: flex-end; }
/*
 * BOS KONUSMA DA AKISIN YERINI TUTAR.
 *
 * `.chat-stream` flex: 1 ile paneli dolduruyor; bu kutuda o yoktu, yani
 * panel icerigi kadar buzusuyor ve yazma kutusu ekranin ortasinda,
 * altinda kocaman bos bir gri ile kaliyordu. Bildirilen hali: "ortada
 * havada".
 */
.chat-empty {
  flex: 1; min-height: 0;
  display: grid; place-items: center; padding: 40px;
}
/* Davet, duvar degil: bu kutu bir seyin yoklugunu degil sizin siranizi
   anlatiyor, o yuzden cerceve yerine yalniz yazi. */
.chat-empty .empty { background: none; border: 0; max-width: 40ch; }
.chat-compose {
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: 14px 22px;
}
/* THE COMPOSE TOOLBAR: one row, every control the same height.
   `.chat-tools-gap` is what pushes Send to the far end - `margin-left:auto`
   on the button itself would fight the recorder when it appears. */
.chat-tools {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 10px;
}
.chat-tools-gap { flex: 1 1 auto; }

/* A label that behaves like a button, holding a screen-reader-reachable
   file input. Not `display:none` on the input: that would take it out of
   the tab order and out of the accessibility tree. */
/*
 * THE FILE BOX. A TARGET, NOT A BUTTON WITH A SENTENCE NEXT TO IT.
 *
 * Measured on the reconciliation screen: the control occupied 370 of 1400
 * available pixels and the rest of the row was empty, twice over, because the
 * screen takes two files. A box that fills its column reads as the input it
 * is, and two of them side by side read as one question.
 *
 * `.filepick-input` lies across the whole box at zero opacity. That is what
 * accepts a dropped file - the browser hands a drop to the input element and
 * nothing else - and it keeps the pointer and the keyboard where they were.
 */
.filepick {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  padding: 11px 12px;
  border: 1px solid var(--border-input);
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.filepick:hover { border-color: var(--accent); background: var(--surface-hover); }
.filepick-input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer;
}
.filepick-mark {
  display: grid; place-items: center; width: 32px; height: 32px; flex: none;
  background: var(--surface-sunken); color: var(--text-icon);
}
/* A CHOSEN FILE CHANGES THE BOX, not just the words in it. */
.filepick.has-file, .filepick.has-files { border-color: var(--ok); }
.filepick.has-file .filepick-mark,
.filepick.has-files .filepick-mark { background: var(--ok-tint); color: var(--ok-text); }
/* The button is a label for the box, not a second target inside it. */
.filepick-btn { pointer-events: none; margin-left: auto; flex: none; }
.filepick-name {
  min-width: 0; flex: 1; font-size: var(--fs-sm); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.filepick.has-file .filepick-name { color: var(--text-body); font-weight: 600; }
/* Birden fazla dosya secildi (`multiple`): app.js hepsinin adini yaziyor, ve
   adlar tek satirda ilkinden sonra kesilmesin diye alt alta sariyor. Tek dosya
   yukaridaki tek satirli, uc noktali haliyle kalir. */
.filepick.has-files .filepick-name { white-space: normal; overflow-wrap: anywhere; }
/* The focus ring goes round the BOX now, because the box is the control. */
.filepick:focus-within {
  outline: 2px solid var(--focus-ring); outline-offset: 2px;
}

.chat-attach { cursor: pointer; max-width: 220px; }
.chat-attach [data-file-name] {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-attach:focus-within {
  outline: 2px solid var(--focus-ring); outline-offset: 2px;
}
.chat-attach.has-file { border-color: var(--accent-solid); color: var(--accent-text); }

.chat-pane { display: flex; flex-direction: column; min-height: 0; }

.chat-info {
  border-left: 1px solid var(--border);
  background: var(--surface-sunken);
  overflow-y: auto; min-height: 0;
  padding: 18px;
}
.chat-info h3 { font-size: var(--fs-md); font-weight: 700; margin-bottom: 4px; }
.chat-info-head { display: grid; justify-items: center; gap: 8px; text-align: center; margin-bottom: 18px; }
.chat-members { list-style: none; display: grid; gap: 10px; }
.chat-members li { display: flex; align-items: center; gap: 10px; }
.chat-member-main { display: grid; gap: 1px; min-width: 0; }
.chat-member-main strong { font-size: var(--fs-sm); font-weight: 700; }
.chat-member-main em { font-style: normal; font-size: var(--fs-2xs); color: var(--text-muted); }

.chat-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.chat-head-main { display: grid; gap: 1px; min-width: 0; }
.chat-head-main strong { font-size: var(--fs-md); font-weight: 700; }
.chat-head-main span { font-size: var(--fs-2xs); color: var(--text-muted); }

/* -- avatar --------------------------------------------------------------- */

/* Round, and sized in one place, so a photograph can drop into the same box
   the day there is one. */
.avatar {
  display: grid; place-items: center; flex: none;
  border-radius: 50%;
  color: var(--text-on-accent);
  font-weight: 700; letter-spacing: 0;
  background: var(--coin-1);
}
.avatar-sm { width: 30px; height: 30px; font-size: 12px; }
.avatar-md { width: 40px; height: 40px; font-size: 14px; }
.avatar-lg { width: 64px; height: 64px; font-size: 22px; }
/* A room is not a person: square corners say so before the label does. */
.avatar-group { border-radius: var(--radius); }
.avatar-hue-0 { background: var(--sidebar-bg-deep); }
.avatar-hue-1 { background: var(--coin-1); }
.avatar-hue-2 { background: var(--coin-2); }
.avatar-hue-3 { background: var(--coin-3); }
.avatar-hue-4 { background: var(--coin-4); }
.avatar-hue-5 { background: var(--coin-5); }
.avatar-hue-6 { background: var(--coin-6); }
.avatar-hue-7 { background: var(--coin-7); }
.avatar-hue-8 { background: var(--coin-8); }
.avatar-hue-9 { background: var(--coin-9); }

/* -- dar ekran ------------------------------------------------------------ */

/* ONE COLUMN AT A TIME, AND THE URL ALREADY SAYS WHICH. `/messages` is the
   list, `/messages/:id` is the conversation - so a narrow screen needs no
   script and no state, only the two rules below. */
@media (max-width: 1100px) {
  .shell-fixed { height: auto; overflow: visible; }
  .shell-fixed .msgrail { border-right: 0; border-bottom: 1px solid var(--border); }
  .chat-with-info { grid-template-columns: minmax(0, 1fr); }
  .chat-info { border-left: 0; border-top: 1px solid var(--border); }
  .shell-fixed.shell-on-conversation .msgrail { display: none; }
}

/* -- mesajlar ------------------------------------------------------------- */

/* Balonlar kartın kendi yüzeyinde yaşıyor; ikinci bir kap açmıyoruz. Renk
   kimin yazdığını söylemenin TEK yolu değil: her balonun başında adı da var,
   çünkü rengi ayırt edemeyen biri için hizalama tek başına bilgi taşımaz. */
.msg-list { list-style: none; display: grid; gap: 12px; margin: 0 0 var(--rhythm); }

.msg {
  display: grid; gap: 4px;
  max-width: 70ch; padding: 10px 12px;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
}
.msg-mine { margin-left: auto; background: var(--surface-band); border-color: var(--border-warm); }

.msg-head { display: flex; align-items: baseline; gap: 10px; }
.msg-who { font-size: var(--fs-2xs); font-weight: 700; color: var(--text-body); }
.msg-at { font-size: var(--fs-2xs); color: var(--text-muted); }

/* YAPIŞIK UZUN METİN SÜTUNU İTMESİN. Boşluksuz bir bağlantı yapıştırıldığında
   satır kırılamaz ve bütün sayfa yana kayar; sebebi metin, görüntüsü yerleşim
   hatasıdır. Bugün bu yalnız .toast-text ve .month-entry'de vardı. */
.msg-body { font-size: var(--fs-sm); line-height: 1.6; color: var(--text-body); overflow-wrap: anywhere; }

.msg-actions { margin-top: 2px; }
.msg-compose { margin-top: var(--rhythm); }

/* Balonun altındaki dosyalar. Hepsi indirme bağlantısı — hiçbiri satır içi
   gösterilmiyor; .svg izin listesinde ve satır içi bir SVG kendi kökenimizde
   saklı XSS demektir. */
.msg-files { list-style: none; display: grid; gap: 4px; margin: 6px 0 0; }
.msg-files li { display: flex; align-items: center; gap: 8px; font-size: var(--fs-2xs); }
.msg-files .icon { flex: none; }

/* Üç durum: nokta RENK, yanındaki kelime BİLGİ. Rengi ayırt edemeyen biri
   için nokta tek başına hiçbir şey söylemez, o yüzden kelime hep yanında. */
.presence { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-2xs); color: var(--text-muted); }
.presence-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-faint); flex: none; }
.presence-online .presence-dot { background: var(--ok-text); }
.presence-away .presence-dot { background: var(--warn-text); }
.presence-online { color: var(--ok-text); }
.presence-away { color: var(--warn-text); }

.field-inline { flex-direction: row; align-items: center; gap: 8px; }

/* -- ses kaydi ------------------------------------------------------------ */

/* Kaydedici VARSAYILAN OLARAK GIZLI. Betik ancak kayit gercekten
   calisabiliyorsa durumu "ready" yapiyor; boylece betiksiz tarayicida ve
   guvenli olmayan adreste calismayacak bir dugme hic cizilmiyor. */
.recorder { display: none; align-items: center; gap: 8px; flex-wrap: wrap; }
.recorder[data-recorder-state="ready"],
.recorder[data-recorder-state="recording"],
.recorder[data-recorder-state="recorded"],
.recorder[data-recorder-state="denied"],
.recorder[data-recorder-state="unavailable"] { display: flex; }

/* Kayit calisabiliyorken sebep cumlesi gereksiz; calismazken dugmeler
   gereksiz. Her halde ekranda tek bir dogru sey duruyor. */
.recorder-unavailable { display: none; }
.recorder[data-recorder-state="unavailable"] .recorder-unavailable { display: block; }
.recorder[data-recorder-state="unavailable"] .btn { display: none; }
.recorder[data-recorder-state="ready"] [data-recorder-stop],
.recorder[data-recorder-state="recorded"] [data-recorder-stop],
.recorder[data-recorder-state="denied"] [data-recorder-stop] { display: none; }
.recorder[data-recorder-state="recording"] [data-recorder-start] { display: none; }

/* ==========================================================================
   CARRIED BACK FROM THE v2.8.0 STYLESHEET

   Replacing app.css wholesale with the newer hub's copy dropped seven
   classes this source still writes, and nothing said so: a class with no
   rule is not an error, it is a plain element. The skip link stopped being
   hidden and sat visible above every page; the performance guide lost its
   two-column layout, its numbered index and its list markers.

   AT THE END, DELIBERATELY. None of these selectors appears anywhere above,
   so the cascade does not care where they sit — and keeping them in one
   block is what lets the next person diff this file against the newer
   stylesheet and see exactly what was added to it.
   ========================================================================== */


.guide-layout {
  display: grid; gap: var(--rhythm);
  grid-template-columns: minmax(0, 1fr) 300px; align-items: start;
}
.guide-side { position: sticky; top: 88px; align-self: start; }
@media (max-width: 1100px) {
  .guide-layout { grid-template-columns: minmax(0, 1fr); }
  .guide-side { position: static; }
}
.guide-lead { max-width: 78ch; color: var(--text-body); }

.guide-list { max-width: 78ch; margin-top: 10px; padding-left: 22px; }
.guide-list { list-style: disc; }
.guide-list-num { list-style: decimal; }
.guide-list li { margin-top: 6px; padding-left: 4px; }
.guide-list li::marker { color: var(--accent-text); font-weight: 700; }

/* Term on the left, rule on the right; stacks under 620px so the terms
   never squeeze to one word per line. */
.guide-defs { margin-top: 12px; max-width: 78ch; }
.guide-defs > div {
  display: grid; grid-template-columns: minmax(140px, 22%) 1fr; gap: 4px 18px;
  padding: 9px 0;
}
.guide-defs > div + div { border-top: 1px solid var(--border-subtle); }
.guide-defs dt {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em;
  color: var(--text-body);
}
.guide-defs dd { color: var(--text-secondary); }

/* The closing line of a section: the thing to remember, set apart with the
   same 3px red bar the hero uses - never a second colour. */
.guide-note {
  margin-top: 12px; max-width: 78ch;
  padding: 9px 0 9px 14px; border-left: 3px solid var(--accent);
  color: var(--text-secondary); font-size: var(--fs-sm);
}

.guide-index ol { list-style: none; counter-reset: guide; }
.guide-index li { counter-increment: guide; }
.guide-index li + li { border-top: 1px solid var(--border-subtle); }
.guide-index a {
  display: flex; gap: 10px; align-items: baseline;
  padding: 8px 0; font-size: var(--fs-sm); color: var(--text-secondary);
}
.guide-index a::before {
  content: counter(guide);
  flex: none; min-width: 14px;
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); color: var(--text-muted);
}
.guide-index a:hover { color: var(--accent-text); }

@media (max-width: 620px) {
  .guide-defs > div { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Card foot, file drop, segmented — shared vocabulary (ui/components.ts)

   Akit is where these were first needed, and they are drawn from the Akit
   application the user pointed at: the dashed box a contract is dropped into,
   the joined "only changes / all paragraphs" switch, the strip under a step
   that ends every panel the same way. They are here as components, not as
   Akit's classes, so the next module that takes a file looks the same.
   ========================================================================== */

/* The foot's note is prose, not the bordered chip `.panel-note` is. */
.card-foot-note { color: var(--text-muted); font-size: var(--fs-xs); line-height: 1.5; min-width: 0; }
.card-foot .row { margin-left: auto; }

.file-drop-grid {
  display: grid; gap: 16px; align-items: stretch;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
/* A select that belongs with the boxes sits level with them, not at the top. */
.file-drop-grid > .field { justify-content: center; min-height: 96px; }

.file-drop {
  position: relative;
  display: flex; align-items: center; gap: 14px; min-height: 96px;
  padding: 14px 20px;
  border: 1.5px dashed var(--border-hover); background: var(--surface-sunken);
  cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.file-drop:hover, .file-drop.is-over {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 4%, var(--surface));
}
.file-drop.is-over { border-style: solid; }
.file-drop:focus-within { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/*
 * THE INPUT IS THE WHOLE BOX, transparent. A dropped file lands on the input
 * itself, which the browser accepts with no script; the visible parts under
 * it are only what the box says.
 */
.file-drop-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }

.file-drop-icon {
  display: grid; place-items: center; flex: 0 0 40px; width: 40px; height: 40px;
  background: var(--surface); color: var(--text-icon); border: 1px solid var(--border-subtle);
}
.file-drop-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.file-drop-role {
  color: var(--accent-text); font-size: var(--fs-xs); line-height: 16px;
  font-weight: 700;
}
.file-drop-text b { font-size: var(--fs-sm); line-height: 20px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-drop-text > span:last-child { color: var(--text-muted); font-size: var(--fs-xs); line-height: 16px; }
/* The button is a picture of one: the click is the box's. */
.file-drop-action { flex: none; pointer-events: none; }

/* Filled — by app.js (`is-filled`), or with script blocked by a required
   input that now holds a file. */
.file-drop.is-filled,
.file-drop:has(.file-drop-input[required]:valid) { border-style: solid; border-color: var(--ok); background: var(--ok-tint); }
.file-drop.is-filled .file-drop-icon,
.file-drop:has(.file-drop-input[required]:valid) .file-drop-icon { color: var(--ok-text); border-color: var(--ok); }

@media (max-width: 620px) {
  .file-drop { flex-wrap: wrap; }
  .file-drop-action { display: none; }
}

/* Two or three views of one list, joined. The current one is filled. */
.segmented { display: inline-flex; flex-wrap: wrap; }
.segmented a {
  display: inline-flex; align-items: center; height: 34px; padding: 0 12px;
  border: 1px solid var(--border-button); background: var(--surface);
  color: var(--text-body); font-size: var(--fs-xs); font-weight: 600; text-decoration: none;
}
.segmented a + a { border-left: 0; }
.segmented a:hover:not([aria-current]) { background: var(--surface-hover); }
.segmented a[aria-current="page"] { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--text-on-accent); }

/* ==========================================================================
   Akit — additions to the recovered contract design (.ctr-*)
   ========================================================================== */

/* The sheet lies on a desk: a sunken band, so the page reads as paper. */
.ctr-desk { background: var(--surface-sunken); padding: 28px 20px; overflow-x: auto; }

/* Word's commonest sizes the recovered set did not have. */
.ctr-sz-10-5 { font-size: 10.5pt; }
.ctr-sz-13 { font-size: 13pt; }

/* Indents in half-centimetre steps, as classes (no inline style). */
.ctr-ind-1 { padding-left: .5cm; }
.ctr-ind-2 { padding-left: 1cm; }
.ctr-ind-3 { padding-left: 1.5cm; }
.ctr-ind-4 { padding-left: 2cm; }
.ctr-ind-5 { padding-left: 2.5cm; }
.ctr-ind-6 { padding-left: 3cm; }
.ctr-ind-7 { padding-left: 3.5cm; }
.ctr-ind-8 { padding-left: 4cm; }
.ctr-page td > p:last-child { margin-bottom: 0; }
.ctr-page ins, .ctr-page del { text-decoration-thickness: 1px; }

/* A line break inside a paragraph; `.ctr-tab` above carries the tab. */
.ctr-br { display: block; }

@media (max-width: 720px) {
  .ctr-desk { padding: 12px 0; }
  .ctr-page { padding: 1cm .8cm; }
  .ctr-ind-5, .ctr-ind-6, .ctr-ind-7, .ctr-ind-8 { padding-left: 2cm; }
}

/*
 * THE COMPARISON'S ROWS, one tint per kind — the tint is the second signal,
 * the label in the left column is the first, and the word-level <ins>/<del>
 * carry underline and strike-through for print and for readers who do not
 * see the difference between the two colours.
 */
.ctr-row-added   { background: color-mix(in srgb, var(--ok-tint) 55%, var(--surface)); }
.ctr-row-removed { background: color-mix(in srgb, var(--error-tint) 55%, var(--surface)); }
.ctr-row-changed { background: color-mix(in srgb, var(--warn-tint) 55%, var(--surface)); }
.ctr-para-kind { display: inline-block; padding: 2px 6px; }
.ctr-row-added .ctr-para-kind   { background: var(--ok-tint); color: var(--ok-text); }
.ctr-row-removed .ctr-para-kind { background: var(--error-tint); color: var(--error-text); }
.ctr-row-changed .ctr-para-kind { background: var(--warn-tint); color: var(--warn-text); }
.ctr-row-same .ctr-para-kind    { background: var(--surface-sunken); }
.ctr-para-where { display: block; margin-top: 6px; color: var(--text-muted); font-size: var(--fs-xs); font-weight: 700; }
.ctr-para-text { font-size: var(--fs-sm); line-height: 1.7; overflow-wrap: anywhere; }
.ctr-row-same .ctr-para-text { color: var(--text-secondary); }

@media (max-width: 620px) {
  .ctr-para { grid-template-columns: 1fr; gap: 6px; padding: 12px 16px; }
}

/* A finding's quoted paragraph: enough to find it in Word, not the contract. */
.ctr-quote {
  display: block; margin-top: 4px; color: var(--text-muted); font-size: var(--fs-xs); line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

/* ==========================================================================
   Akit-1 — the Word view's modes, the comparison's navigation, the format
   fix plan. Generic components first, then the document's own drawing.
   ========================================================================== */

/* A finished step: the circle goes green and carries a tick. */
.panel-step.is-done { background: var(--ok-tint); color: var(--ok-text); }

/* A drop box that already holds the page's document. */
.file-drop.is-chosen { border-style: solid; border-color: var(--ok); background: color-mix(in srgb, var(--ok-tint) 45%, var(--surface)); }
.file-drop.is-chosen .file-drop-icon { color: var(--ok-text); }
.file-drop.is-chosen .file-drop-text > span:last-child { white-space: normal; }

/* Moving through changes: "↑ Önceki · 3 / 12 · Sonraki ↓". */
.change-nav { display: inline-flex; align-items: center; gap: 8px; }
.change-nav-count { min-width: 4.5em; text-align: center; font-size: var(--fs-sm); color: var(--text-secondary); }
.change-steps { display: inline-flex; gap: 2px; margin-top: 6px; }
.change-steps a {
  display: inline-grid; place-items: center; width: 22px; height: 22px;
  border: 1px solid var(--border); color: var(--text-secondary); text-decoration: none; font-size: 13px;
}
.change-steps a:hover { border-color: var(--border-hover); color: var(--text-body); }
.ctr-para-tools { display: block; }

/* An on/off switch that is a link (or a button of a posted form). */
.toggle-switch {
  display: inline-flex; align-items: center; gap: 8px; min-height: 30px; padding: 0 4px;
  color: var(--text-secondary); font-size: var(--fs-sm); text-decoration: none; background: none; border: 0; cursor: pointer;
}
.toggle-switch-track {
  position: relative; width: 30px; height: 16px; flex: none;
  border-radius: var(--radius-full); background: var(--border-input); transition: background var(--speed);
}
.toggle-switch-track::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px;
  border-radius: var(--radius-full); background: var(--surface); transition: transform var(--speed);
}
.toggle-switch[aria-checked="true"] .toggle-switch-track { background: var(--accent-solid); }
.toggle-switch[aria-checked="true"] .toggle-switch-track::after { transform: translateX(14px); }
.toggle-switch:hover { color: var(--text-body); }

/* Two versions side by side: a label column, then the two documents. */
.diff-cols-head, .diff-cols-row { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr) minmax(0, 1fr); }
.diff-cols-head { position: sticky; top: 132px; z-index: 2; background: var(--surface-head); border-bottom: 1px solid var(--border); }
.diff-cols-head > span {
  padding: 8px 12px; color: var(--text-muted);
  font-size: var(--fs-xs); font-weight: 700;
}
.diff-cols-row > div { padding: 10px 12px; border-bottom: 1px solid var(--border-subtle); min-width: 0; }
.diff-cols-cell + .diff-cols-cell { border-left: 1px solid var(--border-subtle); }
/* A heading in capitals is one long word in a half-width column. */
.diff-cols-cell { overflow-wrap: anywhere; }
.diff-cols-cell.is-empty { background: repeating-linear-gradient(135deg, transparent 0 6px, var(--surface-sunken) 6px 12px); }
.diff-cols-added > .diff-cols-label, .diff-cols-added > .diff-cols-cell:not(.is-empty) { background: color-mix(in srgb, var(--ok-tint) 55%, var(--surface)); }
.diff-cols-removed > .diff-cols-label, .diff-cols-removed > .diff-cols-cell:not(.is-empty) { background: color-mix(in srgb, var(--error-tint) 55%, var(--surface)); }
.diff-cols-changed > .diff-cols-label, .diff-cols-changed > .diff-cols-cell { background: color-mix(in srgb, var(--warn-tint) 55%, var(--surface)); }
.diff-cols-added .ctr-para-kind { background: var(--ok-tint); color: var(--ok-text); }
.diff-cols-removed .ctr-para-kind { background: var(--error-tint); color: var(--error-text); }
.diff-cols-changed .ctr-para-kind { background: var(--warn-tint); color: var(--warn-text); }
.diff-cols-row.is-excluded > div { background: var(--surface-sunken); }
.diff-cols-row.is-excluded .ctr-para-kind { background: var(--surface); color: var(--text-muted); }
.diff-cols-notes { margin-top: 8px; font-size: var(--fs-xs); color: var(--text-muted); font-family: var(--font-sans, inherit); }
.diff-cols-notes p { margin: 0 0 2px; }
.diff-cols-label .margin-note-action { display: block; margin-top: 6px; font-size: var(--fs-xs); }
@media (max-width: 900px) {
  .diff-cols-head, .diff-cols-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .diff-cols-label { grid-column: 1 / -1; }
  .diff-cols-head > span:first-child { display: none; }
  .diff-cols-head { position: static; }
}

/* A note pinned to a spot in the document: a small tab that opens below. */
.margin-note { margin: 2px 0 8px; text-align: right; font-family: var(--font-sans, system-ui, sans-serif); text-indent: 0; }
.margin-note > summary {
  display: inline-flex; align-items: center; gap: 6px; padding: 1px 8px; cursor: pointer; list-style: none;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-secondary);
  font-size: 12px; line-height: 18px; font-weight: 600;
}
.margin-note > summary::-webkit-details-marker { display: none; }
.margin-note[open] > summary { border-bottom-color: transparent; }
.margin-note-body {
  text-align: left; padding: 8px 12px; border: 1px solid var(--border); background: var(--surface);
  color: var(--text-body); font-size: 13.5px; line-height: 1.55;
}
.margin-note-body p { margin: 0 0 4px; }
.margin-note-tools { display: flex; align-items: center; gap: 12px; margin-top: 6px !important; }
.margin-note-tools .change-steps { margin-top: 0; }
.margin-note-warn { color: var(--warn-text); }
.margin-note-ok > summary { border-color: var(--ok); color: var(--ok-text); }
.margin-note-warn > summary { border-color: var(--warn); color: var(--warn-text); }
.margin-note-error > summary { border-color: var(--error); color: var(--error-text); }
.margin-note-info > summary { border-color: var(--info); color: var(--info-text); }
.margin-note-action { font-weight: 600; }

/* A plan: what will be done / what will not and why. */
.plan-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--rhythm); }
@media (max-width: 900px) { .plan-grid { grid-template-columns: minmax(0, 1fr); } }
.plan-list { border: 1px solid var(--border); border-top-width: 3px; padding: 12px 14px; background: var(--surface); }
.plan-list-ok { border-top-color: var(--ok); }
.plan-list-warn { border-top-color: var(--warn); }
.plan-list ul { list-style: none; margin: 8px 0 0; padding: 0; }
.plan-list li { padding: 8px 0; border-top: 1px solid var(--border-subtle); display: flex; flex-direction: column; gap: 3px; }
.plan-list li:first-child { border-top: 0; }
.plan-list li.is-off { color: var(--text-muted); }
.plan-list li.is-off .plan-change { text-decoration: line-through; }
.plan-item-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.plan-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.plan-check input { width: 16px; height: 16px; accent-color: var(--accent-solid); }
.plan-meta { color: var(--text-muted); font-size: var(--fs-xs); white-space: nowrap; }
.plan-change { font-size: var(--fs-sm); color: var(--text-secondary); }
.plan-arrow { margin: 0 6px; color: var(--text-muted); }
.plan-detail, .plan-examples { font-size: var(--fs-xs); color: var(--text-secondary); }
.plan-reason { font-size: var(--fs-xs); color: var(--text-muted); }
.plan-examples { font-style: italic; }
.plan-off { color: var(--warn-text); font-size: var(--fs-xs); }
.plan-empty { margin: 8px 0 0; color: var(--text-muted); font-size: var(--fs-sm); }
.plan-intro { margin: 0; color: var(--text-secondary); font-size: var(--fs-sm); line-height: 1.6; }
.plan-downloaded[hidden] { display: none; }
html.js [data-no-script-only] { display: none; }

/* The comparison's archive box, at the foot of step 2. */
.ctr-archive-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 10px; }
.ctr-archive-form .field { min-width: 16rem; }
.ctr-archive-form .field-hint { flex-basis: 100%; }
.ctr-show { display: inline-block; margin-top: 4px; font-size: var(--fs-xs); font-weight: 600; }

/* -- the view: toolbar, notes, focus ---------------------------------------- */

.ctr-toolbar {
  position: sticky; top: 72px; z-index: 3;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 18px;
  padding: 10px var(--card-p); background: var(--surface); border-bottom: 1px solid var(--border);
}
.ctr-toolbar-start, .ctr-toolbar-end { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; }
.ctr-status { font-size: var(--fs-sm); color: var(--warn-text); }
.ctr-view-notes { display: flex; flex-direction: column; gap: 10px; padding: 12px var(--card-p); }
.ctr-view-notes:empty { display: none; }
.ctr-view-notes .alert { margin: 0; }
.ctr-caption { margin: 0; color: var(--text-muted); font-size: var(--fs-xs); }
.ctr-view [id] { scroll-margin-top: 150px; }
@media (max-width: 900px) { .ctr-toolbar { position: static; } .ctr-view [id] { scroll-margin-top: 88px; } }
/* Two file names and two switches do not fit one narrow head: let it wrap. */
.ctr-view .card-title { overflow-wrap: anywhere; }
@media (max-width: 720px) {
  .ctr-view .card-head { flex-wrap: wrap; }
  .ctr-view .card-head > .row { flex-basis: 100%; flex-wrap: wrap; }
}

.ctr-view [data-change] { cursor: pointer; }
.ctr-view .is-focus, .ctr-view [data-change]:target { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctr-wp:target { outline: 2px solid var(--accent); outline-offset: 3px; background: color-mix(in srgb, var(--accent-tint) 55%, transparent); }

/* -- the document: paragraphs ------------------------------------------------ */

.ctr-wp { margin: 0; }
/* The number's own width is its `ctr-nw-*` class; the indent that pulls the
   first line back must not pull the number's text back with it. */
.ctr-wp .ctr-num { display: inline-block; text-indent: 0; }
.ctr-blank { min-height: 1em; }
/* A document's type without a page around it (the side-by-side cells).
   `:where` keeps it at zero weight, so the document's own face and size
   classes on the same element win. */
:where(.ctr-doc) { font-family: "Times New Roman", Times, serif; font-size: 11pt; line-height: 1.5; color: var(--text-body); }
.ctr-page .ctr-table { width: 100%; table-layout: fixed; }
.ctr-hidden { color: var(--text-muted); border-bottom: 1px dotted currentColor; }
.ctr-sup { vertical-align: super; font-size: 65%; }
.ctr-sub { vertical-align: sub; font-size: 65%; }
.ctr-link { color: var(--info-text); text-decoration: underline; }
.ctr-c-red { color: var(--error-text); }
.ctr-c-orange { color: var(--warn-text); }
.ctr-c-green { color: var(--ok-text); }
.ctr-c-blue { color: var(--info-text); }
.ctr-c-purple { color: var(--dept-finance); }
.ctr-c-gray { color: var(--text-muted); }
.ctr-hl-yellow { background: color-mix(in srgb, var(--warn) 28%, var(--surface)); }
.ctr-hl-green { background: color-mix(in srgb, var(--ok) 24%, var(--surface)); }
.ctr-hl-blue { background: color-mix(in srgb, var(--info) 22%, var(--surface)); }
.ctr-hl-red { background: color-mix(in srgb, var(--error) 20%, var(--surface)); }
.ctr-hl-gray { background: var(--surface-sunken); }
.ctr-font-cambria { font-family: Cambria, Georgia, serif; }
.ctr-font-georgia { font-family: Georgia, serif; }
.ctr-font-garamond { font-family: Garamond, "EB Garamond", Georgia, serif; }
.ctr-font-palatino { font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif; }
.ctr-font-verdana { font-family: Verdana, Geneva, sans-serif; }
.ctr-font-tahoma { font-family: Tahoma, Verdana, sans-serif; }
.ctr-font-segoe { font-family: "Segoe UI", system-ui, sans-serif; }
.ctr-font-mono { font-family: "Courier New", Consolas, monospace; }
.ctr-font-sans { font-family: Arial, Helvetica, sans-serif; }
.ctr-font-serif { font-family: "Times New Roman", Times, serif; }

/* Things in a run that are not text: named, never silently dropped. */
.ctr-obj {
  display: inline-block; margin: 0 2px; padding: 0 5px; text-indent: 0;
  border: 1px solid var(--border); color: var(--text-muted); background: var(--surface-sunken);
  font: 600 10px/16px var(--font-sans, system-ui, sans-serif); letter-spacing: .02em; vertical-align: 1px;
}
.ctr-obj-pageBreak, .ctr-section-break {
  display: block; margin: 6pt 0; border: 0; border-top: 1px dashed var(--border-hover); background: none;
  text-align: center; line-height: 0;
}
.ctr-section-break { display: block; color: var(--text-muted); font: 600 10px/0 var(--font-sans, system-ui, sans-serif); }
.ctr-obj-pageBreak { padding: 0; }
.ctr-band + .ctr-band { margin-top: 6px; }
.ctr-page > .ctr-band:first-child { margin-bottom: 12pt; }
.ctr-band .ctr-wp { font-size: 9pt; }

/* -- the document: what a mode marks ------------------------------------------ */

/* The bar stands OUTSIDE the paragraph's left edge: inside it, it would sit
   on a hanging number, which starts at that very edge. */
.ctr-p-changed { background: color-mix(in srgb, var(--warn-tint) 70%, transparent); box-shadow: -5px 0 0 0 var(--warn); }
.ctr-p-added { background: color-mix(in srgb, var(--ok-tint) 70%, transparent); box-shadow: -5px 0 0 0 var(--ok); }
.ctr-p-removed { background: color-mix(in srgb, var(--error-tint) 70%, transparent); box-shadow: -5px 0 0 0 var(--error); }
.ctr-p-blank { outline: 2px solid var(--warn); outline-offset: 1px; }
.ctr-p-clause.is-present { background: color-mix(in srgb, var(--ok-tint) 70%, transparent); box-shadow: -5px 0 0 0 var(--ok); }
.ctr-p-clause.is-suggested { background: color-mix(in srgb, var(--warn-tint) 70%, transparent); box-shadow: -5px 0 0 0 var(--warn); }
.ctr-fix-text { background: color-mix(in srgb, var(--info-tint) 85%, transparent); }
.ctr-fix-paragraph { box-shadow: -5px 0 0 0 var(--info); }
.ctr-fix-noted { box-shadow: -5px 0 0 0 var(--border); }
.ctr-wp.is-excluded { box-shadow: -5px 0 0 0 var(--border-hover); }
.ctr-marker { margin: 4pt 0; padding: 2px 6px; border: 1px dashed var(--border-hover); font-size: 12px; text-indent: 0; }
.ctr-marker .margin-note { margin: 0; text-align: left; }
.ctr-marker-removed { border-color: var(--error); background: color-mix(in srgb, var(--error-tint) 60%, transparent); }
.ctr-marker-added { border-color: var(--ok); background: color-mix(in srgb, var(--ok-tint) 60%, transparent); }

/* "Değişiklik renkleri" off: the document reads clean; nothing is removed. */
.ctr-view.is-plain .ctr-p-changed, .ctr-view.is-plain .ctr-p-added, .ctr-view.is-plain .ctr-p-removed,
.ctr-view.is-plain .ctr-p-clause, .ctr-view.is-plain .ctr-fix-text, .ctr-view.is-plain .ctr-fix-paragraph,
.ctr-view.is-plain .ctr-fix-noted, .ctr-view.is-plain .ctr-wp.is-excluded { background: none; box-shadow: none; }
.ctr-view.is-plain .ctr-p-blank { outline: 0; }
.ctr-view.is-plain .ctr-add, .ctr-view.is-plain .ctr-del { background: none; color: inherit; text-decoration: none; }
.ctr-view.is-plain .ctr-page .margin-note, .ctr-view.is-plain .diff-cols-notes { display: none; }
.ctr-view.is-plain .ctr-marker { background: none; border-color: var(--border); }
.ctr-view.is-plain .diff-cols-row > div { background: none; }
.ctr-view.is-plain .is-focus { outline-color: var(--border-hover); }

/* The document's geometry in classes: Word's values, bucketed. */
.ctr-sb-0 { padding-top: 0pt; } .ctr-sb-2 { padding-top: 2pt; } .ctr-sb-3 { padding-top: 3pt; } .ctr-sb-4 { padding-top: 4pt; } .ctr-sb-6 { padding-top: 6pt; } .ctr-sb-8 { padding-top: 8pt; } .ctr-sb-10 { padding-top: 10pt; } .ctr-sb-12 { padding-top: 12pt; } .ctr-sb-14 { padding-top: 14pt; } .ctr-sb-16 { padding-top: 16pt; } .ctr-sb-18 { padding-top: 18pt; } .ctr-sb-20 { padding-top: 20pt; } .ctr-sb-24 { padding-top: 24pt; } .ctr-sb-30 { padding-top: 30pt; } .ctr-sb-36 { padding-top: 36pt; }
.ctr-sa-0 { padding-bottom: 0pt; } .ctr-sa-2 { padding-bottom: 2pt; } .ctr-sa-3 { padding-bottom: 3pt; } .ctr-sa-4 { padding-bottom: 4pt; } .ctr-sa-6 { padding-bottom: 6pt; } .ctr-sa-8 { padding-bottom: 8pt; } .ctr-sa-10 { padding-bottom: 10pt; } .ctr-sa-12 { padding-bottom: 12pt; } .ctr-sa-14 { padding-bottom: 14pt; } .ctr-sa-16 { padding-bottom: 16pt; } .ctr-sa-18 { padding-bottom: 18pt; } .ctr-sa-20 { padding-bottom: 20pt; } .ctr-sa-24 { padding-bottom: 24pt; } .ctr-sa-30 { padding-bottom: 30pt; } .ctr-sa-36 { padding-bottom: 36pt; }
.ctr-lh-8 { line-height: 0.92; } .ctr-lh-9 { line-height: 1.04; } .ctr-lh-10 { line-height: 1.15; } .ctr-lh-11 { line-height: 1.27; } .ctr-lh-12 { line-height: 1.38; } .ctr-lh-13 { line-height: 1.5; } .ctr-lh-14 { line-height: 1.61; } .ctr-lh-15 { line-height: 1.73; } .ctr-lh-16 { line-height: 1.84; } .ctr-lh-17 { line-height: 1.96; } .ctr-lh-18 { line-height: 2.07; } .ctr-lh-19 { line-height: 2.19; } .ctr-lh-20 { line-height: 2.3; } .ctr-lh-21 { line-height: 2.42; } .ctr-lh-22 { line-height: 2.53; } .ctr-lh-23 { line-height: 2.65; } .ctr-lh-24 { line-height: 2.76; } .ctr-lh-25 { line-height: 2.88; } .ctr-lh-26 { line-height: 2.99; } .ctr-lh-27 { line-height: 3.11; } .ctr-lh-28 { line-height: 3.22; } .ctr-lh-29 { line-height: 3.34; } .ctr-lh-30 { line-height: 3.45; }
.ctr-pl-1 { padding-left: 0.25cm; } .ctr-pl-2 { padding-left: 0.5cm; } .ctr-pl-3 { padding-left: 0.75cm; } .ctr-pl-4 { padding-left: 1cm; } .ctr-pl-5 { padding-left: 1.25cm; } .ctr-pl-6 { padding-left: 1.5cm; } .ctr-pl-7 { padding-left: 1.75cm; } .ctr-pl-8 { padding-left: 2cm; } .ctr-pl-9 { padding-left: 2.25cm; } .ctr-pl-10 { padding-left: 2.5cm; } .ctr-pl-11 { padding-left: 2.75cm; } .ctr-pl-12 { padding-left: 3cm; } .ctr-pl-13 { padding-left: 3.25cm; } .ctr-pl-14 { padding-left: 3.5cm; } .ctr-pl-15 { padding-left: 3.75cm; } .ctr-pl-16 { padding-left: 4cm; } .ctr-pl-17 { padding-left: 4.25cm; } .ctr-pl-18 { padding-left: 4.5cm; } .ctr-pl-19 { padding-left: 4.75cm; } .ctr-pl-20 { padding-left: 5cm; } .ctr-pl-21 { padding-left: 5.25cm; } .ctr-pl-22 { padding-left: 5.5cm; } .ctr-pl-23 { padding-left: 5.75cm; } .ctr-pl-24 { padding-left: 6cm; } .ctr-pl-25 { padding-left: 6.25cm; } .ctr-pl-26 { padding-left: 6.5cm; } .ctr-pl-27 { padding-left: 6.75cm; } .ctr-pl-28 { padding-left: 7cm; } .ctr-pl-29 { padding-left: 7.25cm; } .ctr-pl-30 { padding-left: 7.5cm; } .ctr-pl-31 { padding-left: 7.75cm; } .ctr-pl-32 { padding-left: 8cm; } .ctr-pl-33 { padding-left: 8.25cm; } .ctr-pl-34 { padding-left: 8.5cm; } .ctr-pl-35 { padding-left: 8.75cm; } .ctr-pl-36 { padding-left: 9cm; } .ctr-pl-37 { padding-left: 9.25cm; } .ctr-pl-38 { padding-left: 9.5cm; } .ctr-pl-39 { padding-left: 9.75cm; } .ctr-pl-40 { padding-left: 10cm; }
.ctr-pr-1 { padding-right: 0.25cm; } .ctr-pr-2 { padding-right: 0.5cm; } .ctr-pr-3 { padding-right: 0.75cm; } .ctr-pr-4 { padding-right: 1cm; } .ctr-pr-5 { padding-right: 1.25cm; } .ctr-pr-6 { padding-right: 1.5cm; } .ctr-pr-7 { padding-right: 1.75cm; } .ctr-pr-8 { padding-right: 2cm; } .ctr-pr-9 { padding-right: 2.25cm; } .ctr-pr-10 { padding-right: 2.5cm; } .ctr-pr-11 { padding-right: 2.75cm; } .ctr-pr-12 { padding-right: 3cm; } .ctr-pr-13 { padding-right: 3.25cm; } .ctr-pr-14 { padding-right: 3.5cm; } .ctr-pr-15 { padding-right: 3.75cm; } .ctr-pr-16 { padding-right: 4cm; } .ctr-pr-17 { padding-right: 4.25cm; } .ctr-pr-18 { padding-right: 4.5cm; } .ctr-pr-19 { padding-right: 4.75cm; } .ctr-pr-20 { padding-right: 5cm; } .ctr-pr-21 { padding-right: 5.25cm; } .ctr-pr-22 { padding-right: 5.5cm; } .ctr-pr-23 { padding-right: 5.75cm; } .ctr-pr-24 { padding-right: 6cm; }
.ctr-ti-1 { text-indent: 0.25cm; } .ctr-ti-2 { text-indent: 0.5cm; } .ctr-ti-3 { text-indent: 0.75cm; } .ctr-ti-4 { text-indent: 1cm; } .ctr-ti-5 { text-indent: 1.25cm; } .ctr-ti-6 { text-indent: 1.5cm; } .ctr-ti-7 { text-indent: 1.75cm; } .ctr-ti-8 { text-indent: 2cm; } .ctr-ti-9 { text-indent: 2.25cm; } .ctr-ti-10 { text-indent: 2.5cm; } .ctr-ti-11 { text-indent: 2.75cm; } .ctr-ti-12 { text-indent: 3cm; } .ctr-ti-13 { text-indent: 3.25cm; } .ctr-ti-14 { text-indent: 3.5cm; } .ctr-ti-15 { text-indent: 3.75cm; } .ctr-ti-16 { text-indent: 4cm; } .ctr-ti-17 { text-indent: 4.25cm; } .ctr-ti-18 { text-indent: 4.5cm; } .ctr-ti-19 { text-indent: 4.75cm; } .ctr-ti-20 { text-indent: 5cm; } .ctr-ti-21 { text-indent: 5.25cm; } .ctr-ti-22 { text-indent: 5.5cm; } .ctr-ti-23 { text-indent: 5.75cm; } .ctr-ti-24 { text-indent: 6cm; }
.ctr-tin-1 { text-indent: -0.25cm; } .ctr-tin-2 { text-indent: -0.5cm; } .ctr-tin-3 { text-indent: -0.75cm; } .ctr-tin-4 { text-indent: -1cm; } .ctr-tin-5 { text-indent: -1.25cm; } .ctr-tin-6 { text-indent: -1.5cm; } .ctr-tin-7 { text-indent: -1.75cm; } .ctr-tin-8 { text-indent: -2cm; } .ctr-tin-9 { text-indent: -2.25cm; } .ctr-tin-10 { text-indent: -2.5cm; } .ctr-tin-11 { text-indent: -2.75cm; } .ctr-tin-12 { text-indent: -3cm; } .ctr-tin-13 { text-indent: -3.25cm; } .ctr-tin-14 { text-indent: -3.5cm; } .ctr-tin-15 { text-indent: -3.75cm; } .ctr-tin-16 { text-indent: -4cm; } .ctr-tin-17 { text-indent: -4.25cm; } .ctr-tin-18 { text-indent: -4.5cm; } .ctr-tin-19 { text-indent: -4.75cm; } .ctr-tin-20 { text-indent: -5cm; } .ctr-tin-21 { text-indent: -5.25cm; } .ctr-tin-22 { text-indent: -5.5cm; } .ctr-tin-23 { text-indent: -5.75cm; } .ctr-tin-24 { text-indent: -6cm; }
.ctr-nw-0 { min-width: 0cm; } .ctr-nw-1 { min-width: 0.25cm; } .ctr-nw-2 { min-width: 0.5cm; } .ctr-nw-3 { min-width: 0.75cm; } .ctr-nw-4 { min-width: 1cm; } .ctr-nw-5 { min-width: 1.25cm; } .ctr-nw-6 { min-width: 1.5cm; } .ctr-nw-7 { min-width: 1.75cm; } .ctr-nw-8 { min-width: 2cm; } .ctr-nw-9 { min-width: 2.25cm; } .ctr-nw-10 { min-width: 2.5cm; } .ctr-nw-11 { min-width: 2.75cm; } .ctr-nw-12 { min-width: 3cm; } .ctr-nw-13 { min-width: 3.25cm; } .ctr-nw-14 { min-width: 3.5cm; } .ctr-nw-15 { min-width: 3.75cm; } .ctr-nw-16 { min-width: 4cm; } .ctr-nw-17 { min-width: 4.25cm; } .ctr-nw-18 { min-width: 4.5cm; } .ctr-nw-19 { min-width: 4.75cm; } .ctr-nw-20 { min-width: 5cm; } .ctr-nw-21 { min-width: 5.25cm; } .ctr-nw-22 { min-width: 5.5cm; } .ctr-nw-23 { min-width: 5.75cm; } .ctr-nw-24 { min-width: 6cm; }
.ctr-sz-6 { font-size: 6pt; } .ctr-sz-6-5 { font-size: 6.5pt; } .ctr-sz-7 { font-size: 7pt; } .ctr-sz-7-5 { font-size: 7.5pt; } .ctr-sz-8-5 { font-size: 8.5pt; } .ctr-sz-9-5 { font-size: 9.5pt; } .ctr-sz-11-5 { font-size: 11.5pt; } .ctr-sz-12-5 { font-size: 12.5pt; } .ctr-sz-13-5 { font-size: 13.5pt; } .ctr-sz-14-5 { font-size: 14.5pt; } .ctr-sz-15 { font-size: 15pt; } .ctr-sz-15-5 { font-size: 15.5pt; } .ctr-sz-16-5 { font-size: 16.5pt; } .ctr-sz-17 { font-size: 17pt; } .ctr-sz-17-5 { font-size: 17.5pt; } .ctr-sz-18-5 { font-size: 18.5pt; } .ctr-sz-19 { font-size: 19pt; } .ctr-sz-19-5 { font-size: 19.5pt; } .ctr-sz-20 { font-size: 20pt; } .ctr-sz-21 { font-size: 21pt; } .ctr-sz-22 { font-size: 22pt; } .ctr-sz-23 { font-size: 23pt; } .ctr-sz-24 { font-size: 24pt; } .ctr-sz-25 { font-size: 25pt; } .ctr-sz-26 { font-size: 26pt; } .ctr-sz-27 { font-size: 27pt; } .ctr-sz-28 { font-size: 28pt; } .ctr-sz-29 { font-size: 29pt; } .ctr-sz-30 { font-size: 30pt; } .ctr-sz-32 { font-size: 32pt; } .ctr-sz-36 { font-size: 36pt; } .ctr-sz-40 { font-size: 40pt; } .ctr-sz-48 { font-size: 48pt; } .ctr-sz-60 { font-size: 60pt; } .ctr-sz-72 { font-size: 72pt; }
.ctr-pw-10 { max-width: 10cm; } .ctr-pw-11 { max-width: 11cm; } .ctr-pw-12 { max-width: 12cm; } .ctr-pw-13 { max-width: 13cm; } .ctr-pw-14 { max-width: 14cm; } .ctr-pw-15 { max-width: 15cm; } .ctr-pw-16 { max-width: 16cm; } .ctr-pw-17 { max-width: 17cm; } .ctr-pw-18 { max-width: 18cm; } .ctr-pw-19 { max-width: 19cm; } .ctr-pw-20 { max-width: 20cm; } .ctr-pw-21 { max-width: 21cm; } .ctr-pw-22 { max-width: 22cm; } .ctr-pw-23 { max-width: 23cm; } .ctr-pw-24 { max-width: 24cm; } .ctr-pw-25 { max-width: 25cm; } .ctr-pw-26 { max-width: 26cm; } .ctr-pw-27 { max-width: 27cm; } .ctr-pw-28 { max-width: 28cm; } .ctr-pw-29 { max-width: 29cm; } .ctr-pw-30 { max-width: 30cm; } .ctr-pw-31 { max-width: 31cm; } .ctr-pw-32 { max-width: 32cm; } .ctr-pw-33 { max-width: 33cm; } .ctr-pw-34 { max-width: 34cm; } .ctr-pw-35 { max-width: 35cm; } .ctr-pw-36 { max-width: 36cm; } .ctr-pw-37 { max-width: 37cm; } .ctr-pw-38 { max-width: 38cm; } .ctr-pw-39 { max-width: 39cm; } .ctr-pw-40 { max-width: 40cm; } .ctr-pw-41 { max-width: 41cm; } .ctr-pw-42 { max-width: 42cm; }
.ctr-mt-0 { padding-top: 0cm; } .ctr-mt-1 { padding-top: 0.25cm; } .ctr-mt-2 { padding-top: 0.5cm; } .ctr-mt-3 { padding-top: 0.75cm; } .ctr-mt-4 { padding-top: 1cm; } .ctr-mt-5 { padding-top: 1.25cm; } .ctr-mt-6 { padding-top: 1.5cm; } .ctr-mt-7 { padding-top: 1.75cm; } .ctr-mt-8 { padding-top: 2cm; } .ctr-mt-9 { padding-top: 2.25cm; } .ctr-mt-10 { padding-top: 2.5cm; } .ctr-mt-11 { padding-top: 2.75cm; } .ctr-mt-12 { padding-top: 3cm; } .ctr-mt-13 { padding-top: 3.25cm; } .ctr-mt-14 { padding-top: 3.5cm; } .ctr-mt-15 { padding-top: 3.75cm; } .ctr-mt-16 { padding-top: 4cm; } .ctr-mt-17 { padding-top: 4.25cm; } .ctr-mt-18 { padding-top: 4.5cm; } .ctr-mt-19 { padding-top: 4.75cm; } .ctr-mt-20 { padding-top: 5cm; } .ctr-mt-21 { padding-top: 5.25cm; } .ctr-mt-22 { padding-top: 5.5cm; } .ctr-mt-23 { padding-top: 5.75cm; } .ctr-mt-24 { padding-top: 6cm; }
.ctr-mr-0 { padding-right: 0cm; } .ctr-mr-1 { padding-right: 0.25cm; } .ctr-mr-2 { padding-right: 0.5cm; } .ctr-mr-3 { padding-right: 0.75cm; } .ctr-mr-4 { padding-right: 1cm; } .ctr-mr-5 { padding-right: 1.25cm; } .ctr-mr-6 { padding-right: 1.5cm; } .ctr-mr-7 { padding-right: 1.75cm; } .ctr-mr-8 { padding-right: 2cm; } .ctr-mr-9 { padding-right: 2.25cm; } .ctr-mr-10 { padding-right: 2.5cm; } .ctr-mr-11 { padding-right: 2.75cm; } .ctr-mr-12 { padding-right: 3cm; } .ctr-mr-13 { padding-right: 3.25cm; } .ctr-mr-14 { padding-right: 3.5cm; } .ctr-mr-15 { padding-right: 3.75cm; } .ctr-mr-16 { padding-right: 4cm; } .ctr-mr-17 { padding-right: 4.25cm; } .ctr-mr-18 { padding-right: 4.5cm; } .ctr-mr-19 { padding-right: 4.75cm; } .ctr-mr-20 { padding-right: 5cm; } .ctr-mr-21 { padding-right: 5.25cm; } .ctr-mr-22 { padding-right: 5.5cm; } .ctr-mr-23 { padding-right: 5.75cm; } .ctr-mr-24 { padding-right: 6cm; }
.ctr-mb-0 { padding-bottom: 0cm; } .ctr-mb-1 { padding-bottom: 0.25cm; } .ctr-mb-2 { padding-bottom: 0.5cm; } .ctr-mb-3 { padding-bottom: 0.75cm; } .ctr-mb-4 { padding-bottom: 1cm; } .ctr-mb-5 { padding-bottom: 1.25cm; } .ctr-mb-6 { padding-bottom: 1.5cm; } .ctr-mb-7 { padding-bottom: 1.75cm; } .ctr-mb-8 { padding-bottom: 2cm; } .ctr-mb-9 { padding-bottom: 2.25cm; } .ctr-mb-10 { padding-bottom: 2.5cm; } .ctr-mb-11 { padding-bottom: 2.75cm; } .ctr-mb-12 { padding-bottom: 3cm; } .ctr-mb-13 { padding-bottom: 3.25cm; } .ctr-mb-14 { padding-bottom: 3.5cm; } .ctr-mb-15 { padding-bottom: 3.75cm; } .ctr-mb-16 { padding-bottom: 4cm; } .ctr-mb-17 { padding-bottom: 4.25cm; } .ctr-mb-18 { padding-bottom: 4.5cm; } .ctr-mb-19 { padding-bottom: 4.75cm; } .ctr-mb-20 { padding-bottom: 5cm; } .ctr-mb-21 { padding-bottom: 5.25cm; } .ctr-mb-22 { padding-bottom: 5.5cm; } .ctr-mb-23 { padding-bottom: 5.75cm; } .ctr-mb-24 { padding-bottom: 6cm; }
.ctr-ml-0 { padding-left: 0cm; } .ctr-ml-1 { padding-left: 0.25cm; } .ctr-ml-2 { padding-left: 0.5cm; } .ctr-ml-3 { padding-left: 0.75cm; } .ctr-ml-4 { padding-left: 1cm; } .ctr-ml-5 { padding-left: 1.25cm; } .ctr-ml-6 { padding-left: 1.5cm; } .ctr-ml-7 { padding-left: 1.75cm; } .ctr-ml-8 { padding-left: 2cm; } .ctr-ml-9 { padding-left: 2.25cm; } .ctr-ml-10 { padding-left: 2.5cm; } .ctr-ml-11 { padding-left: 2.75cm; } .ctr-ml-12 { padding-left: 3cm; } .ctr-ml-13 { padding-left: 3.25cm; } .ctr-ml-14 { padding-left: 3.5cm; } .ctr-ml-15 { padding-left: 3.75cm; } .ctr-ml-16 { padding-left: 4cm; } .ctr-ml-17 { padding-left: 4.25cm; } .ctr-ml-18 { padding-left: 4.5cm; } .ctr-ml-19 { padding-left: 4.75cm; } .ctr-ml-20 { padding-left: 5cm; } .ctr-ml-21 { padding-left: 5.25cm; } .ctr-ml-22 { padding-left: 5.5cm; } .ctr-ml-23 { padding-left: 5.75cm; } .ctr-ml-24 { padding-left: 6cm; }
.ctr-w-5 { width: 5%; } .ctr-w-10 { width: 10%; } .ctr-w-15 { width: 15%; } .ctr-w-20 { width: 20%; } .ctr-w-25 { width: 25%; } .ctr-w-30 { width: 30%; } .ctr-w-35 { width: 35%; } .ctr-w-40 { width: 40%; } .ctr-w-45 { width: 45%; } .ctr-w-50 { width: 50%; } .ctr-w-55 { width: 55%; } .ctr-w-60 { width: 60%; } .ctr-w-65 { width: 65%; } .ctr-w-70 { width: 70%; } .ctr-w-75 { width: 75%; } .ctr-w-80 { width: 80%; } .ctr-w-85 { width: 85%; } .ctr-w-90 { width: 90%; } .ctr-w-95 { width: 95%; } .ctr-w-100 { width: 100%; }

/* On a phone the page is the screen: the document's margins and width give way. */
@media (max-width: 720px) {
  .ctr-page[class] { padding: 1cm .8cm; max-width: none; }
  .ctr-wp[class*="ctr-pl-"] { padding-left: min(2cm, 12vw); }
}

/* On paper: the result, not its controls. */
@media print {
  .ctr-toolbar, .change-steps, .margin-note-tools, .ctr-view .segmented, .toggle-switch,
  .ctr-view-notes .disclosure { display: none !important; }
  .ctr-desk { background: none; padding: 0; }
  .ctr-page { box-shadow: none; border: 0; }
  .ctr-view .is-focus { outline: 0; }
}


/*
 * THE REQUEST FORM: the form, and beside it the required fields as a
 * checklist — each a link to its box, done ones quiet, refused ones red.
 */
.request-layout { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 24px; align-items: start; }
.request-side { position: sticky; top: 88px; }
.request-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 18px; }
.request-wide { grid-column: 1 / -1; }
.request-cell, .request-wide { min-width: 0; }
.request-group {
  grid-column: 1 / -1; margin: 10px 0 0; padding-bottom: 6px; border-bottom: 1px solid var(--border-subtle);
  color: var(--accent-text); font-size: var(--fs-xs); font-weight: 700;
}
.request-group:first-child { margin-top: 0; }
.request-checklist { list-style: none; margin: 0; padding: 0; font-size: var(--fs-sm); }
.request-checklist li + li { border-top: 1px solid var(--border-subtle); }
.request-checklist a { display: flex; gap: 8px; align-items: center; text-decoration: none; }
@media (max-width: 960px) {
  .request-layout { grid-template-columns: minmax(0, 1fr); }
  .request-side { position: static; }
}
@media (max-width: 720px) { .request-grid { grid-template-columns: minmax(0, 1fr); } }

/* The front page's tools: three across, like the original's quick start. */
.akit-tiles { display: grid; gap: var(--rhythm); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.akit-tiles .tile { min-height: 0; }
@media (max-width: 1100px) { .akit-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .akit-tiles { grid-template-columns: minmax(0, 1fr); } }

/* A manual topic's number is the book's, so it is the filled accent disc of
   the recovered design rather than the tinted step of an ordinary panel. */
.manual-topic .panel-step {
  width: 36px; height: 36px; font-size: 16px;
  background: var(--accent-solid); color: var(--text-on-accent);
}

/* A short column of facts (components.ts keyValues): label left, value right,
   a hairline between. */
.kv-list { margin: 0; }
.kv-list > div {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding: 9px 0; border-bottom: 1px solid var(--border-subtle);
}
.kv-list > div:last-child { border-bottom: 0; }
.kv-list dt { color: var(--text-secondary); font-size: var(--fs-sm); }
.kv-list dd { margin: 0; font-variant-numeric: tabular-nums; font-weight: 700; font-size: var(--fs-sm); text-align: right; font-variant-numeric: tabular-nums; }
.kv-group {
  margin: 14px 0 2px; color: var(--accent-text); font-size: var(--fs-xs);
  font-weight: 700;
}
.kv-group:first-child { margin-top: 0; }

/* Three across (a comparison's charts and its summary). */
.chart-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1200px) { .chart-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 900px) { .chart-grid-3 { grid-template-columns: minmax(0, 1fr); } }
/* A row whose two halves go to the two edges, wrapping when they meet. */
.row-between { justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: 12px 24px; }

/* A coin with its trading pair under it ("XCN" over "XCNTRY"). */
.coin-name { display: inline-flex; flex-direction: column; line-height: 1.2; }
.coin-pair { color: var(--text-muted); font-size: var(--fs-2xs); font-weight: 400; }
/* Figures in a table do not break between the number and its unit:
   "269,7 M ₺" split over two lines read as two values. */
.table .money, .table .num { white-space: nowrap; }
/* Cards inside a grid are side by side: the page's vertical rhythm
   (`* + * { margin-top }`) pushed every card after the first 16px down. */
.chart-grid > * + *, .chart-grid > .card + .card { margin-top: 0; }

/* A row of small rounded links (components.ts chipList). */
.chip-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.chip-list .chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px 3px 4px; border-radius: var(--radius-full);
  background: var(--surface-sunken); border: 1px solid var(--border-subtle);
  color: var(--text-body); font-size: var(--fs-xs); font-weight: 700; text-decoration: none;
}
.chip-list .chip:hover { border-color: var(--accent); color: var(--accent-text); }
.chip-list .chip .coin-mark { transform: scale(.8); }

/* Many-of-many as chips (components.ts checkChips). */
.check-chips { border: 0; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.check-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px; border: 1px solid var(--border); background: var(--surface);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-secondary); cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.check-chip input { margin: 0; accent-color: var(--accent-solid); }
.check-chip small { color: var(--text-muted); font-weight: 400; font-size: var(--fs-2xs); }
.check-chip:hover { border-color: var(--border-hover); }
.check-chip:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); color: var(--text-body); }
.check-chip:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* A ranking block (components.ts rankedList). */
.ranked-lists { display: grid; gap: var(--rhythm); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.ranked-lists > * + * { margin-top: 0; }
.ranked-list {
  background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--accent);
  box-shadow: var(--shadow-card); padding: 16px var(--card-p);
}
.ranked-list-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 10px; }
.ranked-list-head p { margin: 0; font-size: var(--fs-xs); font-weight: 700; color: var(--accent-text); }
.ranked-list-head span { font-size: var(--fs-2xs); color: var(--text-muted); }
.ranked-list ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.ranked-list li { display: flex; gap: 12px; align-items: baseline; font-size: var(--fs-sm); }
.ranked-list li b {
  flex: 0 0 24px; height: 24px; display: grid; place-items: center;
  border-radius: var(--radius-full); background: var(--accent-tint); color: var(--accent-text);
  font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
}
.ranked-list li span { font-weight: 600; }

/* A board card's section heading ("PAY SENEDİ · TOPLAM" once, not per row). */
.board-section {
  margin: 10px 0 0; padding-top: 8px; border-top: 1px solid var(--border);
  font-size: var(--fs-xs); font-weight: 700; color: var(--accent-text);
}
.board-count { font-size: var(--fs-2xs); color: var(--text-muted); font-weight: 600; white-space: nowrap; }

/* A step's own date card: the number, what it is, its picker. */
.date-steps { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 12px; align-items: stretch; }
.date-steps > * + * { margin-top: 0; }
.date-step-card {
  display: flex; align-items: center; gap: 14px; padding: 14px var(--card-p);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-card);
}
.date-step-card .field { flex: 1; min-width: 0; }
.date-step-swap { align-self: center; }
@media (max-width: 760px) { .date-steps { grid-template-columns: minmax(0, 1fr); } }

/* A category's recorded days as small date chips. */
.day-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.day-chips span {
  padding: 2px 8px; border: 1px solid var(--border-subtle); background: var(--surface-sunken);
  font-variant-numeric: tabular-nums; font-size: var(--fs-2xs); color: var(--text-secondary);
}
.day-chips .day-chips-more { font-family: inherit; font-weight: 700; color: var(--text-muted); }
/* The exact figure MKK prints in brackets, under the rounded one. */
.board-exact { display: block; font-weight: 400; color: var(--text-muted); font-size: var(--fs-2xs); }

/* A pick tile's tick and its one-click action (components.ts pickTile). */
.pick-tile input { flex: none; accent-color: var(--accent-solid); margin: 0; }
.pick-tile .btn { justify-self: end; }

/* Asked twice (components.ts confirmAction): the summary is the button, the
   question opens under it. */
.confirm { position: relative; display: inline-block; }
.confirm > summary { list-style: none; cursor: pointer; }
.confirm > summary::-webkit-details-marker { display: none; }
.confirm[open] > summary { box-shadow: 0 0 0 2px var(--focus-ring); }
.confirm-pop {
  position: absolute; z-index: 20; top: calc(100% + 6px); right: 0;
  width: min(340px, 90vw); padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--error);
  box-shadow: var(--shadow-overlay, var(--shadow-lift));
  display: grid; gap: 6px;
}
.confirm-pop p { margin: 0; color: var(--text-secondary); font-size: var(--fs-sm); }
/* The same question for a button that cannot be a confirmAction (app.js askInApp): over the page, in the app's frame. */
.app-confirm {
  width: min(420px, calc(100vw - 32px)); padding: 18px 20px; margin: auto;
  color: var(--text-body); background: var(--surface);
  border: 1px solid var(--border); border-top: 3px solid var(--error); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-overlay, var(--shadow-lift));
}
.app-confirm[open] { display: grid; gap: 8px; }
.app-confirm::backdrop { background: rgb(15 23 42 / 0.45); }
.app-confirm .label { margin: 0; }
.app-confirm p:not(.label) { margin: 0; color: var(--text-secondary); font-size: var(--fs-sm); }
.app-confirm .row { justify-content: flex-end; margin-top: 10px; }
.confirm-pop .row { justify-content: space-between; align-items: center; margin-top: 6px; }
/* A tile with no tick column (a catalogue that adds by button). */
.pick-tile.pick-tile-plain { grid-template-columns: auto auto minmax(0, 1fr) auto; }

/* ==========================================================================
   Hacim parity: a long action's progress panel, the period picker, the
   "+N" chip, a confirmation that carries its own fields.
   ========================================================================== */

/* components.ts liveProgress — the original volume app's LoadingProgress:
   bottom centre, over the page, while the fetch POST runs. */
.live-progress {
  position: fixed; z-index: 190; left: 50%; bottom: 24px; transform: translateX(-50%);
  width: min(420px, calc(100vw - 32px)); padding: 12px 16px;
  background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--accent);
  box-shadow: var(--shadow-overlay);
  display: grid; gap: 8px;
}
.live-progress[hidden] { display: none; }
.live-progress-head {
  margin: 0; display: flex; justify-content: space-between; gap: 12px;
  font-size: var(--fs-xs); font-weight: 700;
  color: var(--text-muted);
}
.live-progress-step { font-variant-numeric: tabular-nums; }
.live-progress-track {
  display: block; height: 6px; overflow: hidden;
  border-radius: var(--radius-full); background: var(--surface-sunken);
}
.live-progress-track > span {
  display: block; height: 100%; width: 40%; border-radius: inherit; background: var(--accent);
  animation: progress-slide 1.2s ease-in-out infinite;
}
.live-progress-message {
  margin: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--text-body);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) {
  .live-progress-track > span { animation: none; width: 100%; opacity: .6; }
}
:root[data-motion="off"] .live-progress-track > span { animation: none; width: 100%; opacity: .6; }

/* The period switch, its end day and the date-range disclosure (volume). */
.period-picker { display: grid; gap: 12px; }
.period-picker > .row { align-items: flex-end; flex-wrap: wrap; gap: 12px 16px; }
.period-picker .filters { margin: 0; }
.period-picker .filters > .field-hint {
  flex-basis: 100%; margin: 0; display: flex; align-items: center; gap: 8px;
}

/* A chip for what the list left off ("+12") — plain text, not a link. */
.chip-list .chip.chip-more { padding: 3px 10px; color: var(--text-muted); }

/* confirmAction with controls of its own (a file to import). */
.confirm-form { display: grid; gap: 10px; }
.confirm-form > .row { justify-content: space-between; align-items: center; }
/* A question opened inside a table (the backup list's "Sil") must not be
   cut off by the table's own scroll box: while it is open the box lets it
   overflow; closed, the table scrolls sideways as before. */
.scroll-x:has(.confirm[open]) { overflow: visible; }

/* ==========================================================================
   MKK parity: the board's rows, marks and shortcuts, marked chips, the
   preview's faded "Veri yok" days and its heading that stays in view.
   ========================================================================== */

/* A FOLDED CARD'S ROW SHRINKS WITH IT. Stretched rows kept a folded card as
   tall as the longest one beside it (the original's `.market-grid`). */
.board.board-foldable { align-items: start; }

/* The pick mark: a plus while out, a tick while in (the original's). The
   plus is quiet; the filled box with a tick is the selected state. */
.board-mark.board-mark-pick { color: var(--text-muted); }
.board-mark-pick > span { display: grid; place-items: center; }
.board-mark-pick .mark-on { display: none; }
.board-card:has(> input:checked) .board-mark-pick .mark-on { display: grid; }
.board-card:has(> input:checked) .board-mark-pick .mark-off { display: none; }

/* "Tümünü seç" / "Seçimi temizle" while they describe the selection. */
.btn[data-shortcut][aria-current="true"] {
  border-color: var(--accent-solid); background: var(--accent-solid); color: var(--text-on-accent);
}

/* checkChips({ marks }): the chip's own plus / tick instead of a box —
   only where :has() can show the state (the box stays otherwise). */
.check-chip-mark { display: none; }
@supports selector(:has(*)) {
  .check-chips-marked .check-chip { position: relative; }
  .check-chips-marked .check-chip > input {
    position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none;
  }
  .check-chips-marked .check-chip-mark { display: inline-grid; place-items: center; color: var(--text-muted); }
  .check-chips-marked .check-chip-mark > span { display: inline-grid; place-items: center; }
  .check-chips-marked .check-chip-mark .mark-on { display: none; }
  .check-chips-marked .check-chip:has(input:checked) .check-chip-mark { color: var(--accent-text); }
  .check-chips-marked .check-chip:has(input:checked) .mark-on { display: inline-grid; }
  .check-chips-marked .check-chip:has(input:checked) .mark-off { display: none; }
}

/* The preview: a day without data is faded and slanted, as the file greys it. */
.table tbody tr.row-missing td,
.table.striped tbody tr.row-missing td {
  color: var(--text-muted); font-style: italic; background: var(--surface-sunken);
}
/* A category's heading stays under the top strip while its rows scroll. */
.card-sticky-head > .card-head {
  position: sticky; top: 72px; z-index: 5;
  background: var(--surface);
}
.preview-meta { padding: 8px var(--card-p) 0; }
.preview-jump { align-items: center; gap: 10px; flex-wrap: wrap; }
.preview-jump .chip-list { margin: 0; }

/* A client toast's heading over its words (app.js clientToast). */
[data-client-toast] .toast-title { display: block; margin-bottom: 2px; }

/* ==========================================================================
   Akit parity — shared pieces first (components.ts), then Akit's own.

   pageHead `guide`, segmented `submit`, markChips, bulletList,
   printIdentity, statusCard `body`, field `emptyTag`, and the print rules
   that let a result print while its form does not.
   ========================================================================== */

/* "?" beside a page's title: the page's topic in the manual. */
.page-head-title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.page-guide {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--text-secondary); font-size: var(--fs-xs); font-weight: 600; text-decoration: none;
}
.page-guide-mark {
  display: inline-grid; place-items: center; width: 22px; height: 22px;
  border: 1.5px solid currentColor; border-radius: var(--radius-full);
  font-size: 13px; font-weight: 700; line-height: 1;
}
.page-guide:hover, .page-guide:focus-visible { color: var(--accent-text); }

/* The joined switch as buttons of a form (segmented `submit`). */
.segmented button {
  display: inline-flex; align-items: center; height: 34px; padding: 0 12px;
  border: 1px solid var(--border-button); background: var(--surface);
  color: var(--text-body); font: inherit; font-size: var(--fs-xs); font-weight: 600; cursor: pointer;
}
.segmented button + button { border-left: 0; }
.segmented button:hover:not([aria-pressed="true"]) { background: var(--surface-hover); }
.segmented button[aria-pressed="true"] { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--text-on-accent); }

/* Words marked found or missing (components.ts markChips). */
.mark-chips { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.mark-chip {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px;
  border-radius: var(--radius-full); font-size: var(--fs-xs); font-weight: 600; line-height: 20px;
}
.mark-chip.is-ok { background: var(--ok-tint); color: var(--ok-text); }
.mark-chip.is-missing { background: var(--error-tint); color: var(--error-text); }

/* An alert that holds a title and a list (components.ts callout). */
.callout-body { display: grid; gap: 4px; min-width: 0; font-weight: 400; }
.callout-body > p { margin: 0; }
.callout-title { font-weight: 700; }
.callout .bullet-list { margin-top: 2px; }

/* Sentences as bullets (components.ts bulletList) — also inside an alert. */
.bullet-list { margin: 6px 0 0; padding-left: 20px; font-weight: 400; line-height: 1.65; }
.bullet-list li + li { margin-top: 2px; }
.alert .bullet-list { color: inherit; }

/* More than a sentence inside a status banner (statusCard `body`). */
.status-body { display: grid; gap: 10px; margin-top: 10px; }
.status-body:empty { display: none; }
/* The banner's own title rule (`.status strong`) is not for what sits in its body. */
.status-body strong { display: inline; font-size: inherit; font-weight: 700; }
.status-body .callout-title { display: block; }
.status-body .bullet-list { color: var(--text-body); font-size: var(--fs-sm); }
.status-body .callout .bullet-list { color: inherit; }

/* "boş · şablonda boş kalır" beside an empty box's label (field `emptyTag`). */
.field-tag {
  margin-left: 8px; padding: 1px 7px; border-radius: var(--radius-full);
  background: var(--warn-tint); color: var(--warn-text);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0; text-transform: none;
}
.field-tag[hidden] { display: none; }

/* Where a tool's result begins: the target of `#sonuc`, clear of the sticky top strip. */
.result-anchor { height: 0; scroll-margin-top: 88px; }
.result-anchor:focus { outline: none; }
main > .result-anchor, .main > .result-anchor { margin-top: 0; }
[id^="sonuc"] { scroll-margin-top: 88px; }

/* Only on paper: the identity line; only on screen: the forms a result came from. */
.print-identity {
  margin: 0 0 12px; padding-bottom: 6px; border-bottom: 1px solid var(--border);
  color: var(--text-secondary); font-size: 10pt;
}
@media print {
  .screen-only, .page-guide, .result-anchor, .confirm, .segmented { display: none !important; }
  .mark-chip { border: 1px solid currentColor; }
}

/* -- Akit: the clause check ---------------------------------------------- */
.clause-no { color: var(--text-muted); font-variant-numeric: tabular-nums; margin-right: 2px; }
.clause-reason { display: block; margin-top: 4px; color: var(--text-secondary); font-size: var(--fs-sm); line-height: 1.55; }
.clause-note { margin-top: 4px; font-size: var(--fs-sm); }
.table .clause-verdict { width: 240px; }
.clause-verdict .field + .field { margin-top: 8px; }

/* -- Akit: the checklist editor ------------------------------------------- */
.table td .field + .choice-option { margin-top: 6px; }

/* ==========================================================================
   Müşteri Mutabakat — the generic parts first (fileList, noticeList,
   pickCards, progressReport, liveProgress's filling bar), then the page.
   ========================================================================== */

/* components.ts fileList — the files a box already holds. */
.file-list {
  margin-top: 10px; max-height: 180px; overflow-y: auto;
  border: 1px solid var(--border-subtle); background: var(--surface);
}
.file-list li {
  display: flex; align-items: center; gap: 9px; padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle); font-size: var(--fs-sm); color: var(--text-body);
}
.file-list li:last-child { border-bottom: 0; }
.file-list-mark { flex: none; color: var(--ok-text); font-weight: 800; }
.file-list .is-more .file-list-mark, .file-list .is-more .file-list-name { color: var(--text-muted); }
.file-list-name { min-width: 0; overflow-wrap: anywhere; }
.file-list-meta { margin-left: auto; flex: none; color: var(--text-muted); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }

/* components.ts noticeList — a check's verdict on each file. */
.notice-list { display: grid; gap: 8px; }
.notice-row {
  display: flex; gap: 11px; align-items: flex-start; padding: 11px 12px;
  border: 1px solid var(--border-subtle); border-left: 3px solid var(--ok); background: var(--ok-tint);
}
.notice-row.notice-warn { border-left-color: var(--warn); background: var(--warn-tint); }
.notice-row.notice-error { border-left-color: var(--error); background: var(--error-tint); }
.notice-mark {
  display: grid; place-items: center; flex: none; width: 22px; height: 22px;
  border: 1.5px solid currentColor; border-radius: var(--radius-full);
  background: var(--surface); color: var(--ok-text); font-size: var(--fs-xs); font-weight: 800;
}
.notice-warn .notice-mark { color: var(--warn-text); }
.notice-error .notice-mark { color: var(--error-text); }
.notice-text { min-width: 0; }
.notice-text b { display: block; font-size: var(--fs-sm); color: var(--text-body); overflow-wrap: anywhere; }
.notice-text small { display: block; margin-top: 3px; font-size: var(--fs-xs); line-height: 1.5; color: var(--text-secondary); overflow-wrap: anywhere; }

/* components.ts pickCards — cards to open one of, each with its own action. */
.pick-cards { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.pick-card { display: flex; flex-direction: column; border: 1px solid var(--border); background: var(--surface); }
.pick-card.is-active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.pick-card.is-error { border-color: var(--error); background: var(--error-tint); }
.pick-card-open { flex: 1; display: grid; gap: 10px; align-content: start; padding: 14px; color: inherit; text-decoration: none; }
a.pick-card-open:hover { background: var(--surface-sunken); }
.pick-card.is-active a.pick-card-open:hover { background: transparent; }
.pick-card-head { display: flex; gap: 8px; align-items: flex-start; justify-content: space-between; }
.pick-card-title { min-width: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); overflow-wrap: anywhere; }
.pick-card-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.pick-card-facts .label { display: block; }
.pick-card-facts b { display: block; margin-top: 2px; font-size: var(--fs-sm); color: var(--text-body); }
.pick-card-note { font-size: var(--fs-xs); color: var(--text-secondary); overflow-wrap: anywhere; }
.pick-card-action { padding: 0 14px 14px; }
.pick-card-action form, .pick-card-action .btn { width: 100%; }
.pick-card-action .btn { justify-content: center; }

/* A <progress> drawn in the hub's colours — progressReport, and liveProgress({meter}). */
.progress-meter {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: 8px; border: 0; overflow: hidden;
  border-radius: var(--radius-full); background: var(--surface-sunken); color: var(--accent);
}
.progress-meter::-webkit-progress-bar { background: var(--surface-sunken); border-radius: var(--radius-full); }
.progress-meter::-webkit-progress-value { background: var(--accent); border-radius: var(--radius-full); }
.progress-meter::-moz-progress-bar { background: var(--accent); border-radius: var(--radius-full); }
.progress-meter[hidden], .live-progress-track[hidden] { display: none; }
.progress-report { display: grid; gap: 8px; }
.progress-report-title { margin: 0; font-weight: 700; color: var(--text-body); }
.progress-report-detail { margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.progress-report.is-ok .progress-meter::-webkit-progress-value { background: var(--ok); }
.progress-report.is-ok .progress-meter::-moz-progress-bar { background: var(--ok); }
.progress-report.is-error .progress-meter::-webkit-progress-value { background: var(--error); }
.progress-report.is-error .progress-meter::-moz-progress-bar { background: var(--error); }

/* -- the reconciliation page ----------------------------------------------------- */
.recon-page > * + * { margin-top: var(--rhythm); }
.recon-lead { margin: 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-secondary); }
.recon-upload { display: grid; gap: var(--rhythm); grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
/* Side by side, not stacked: a sibling card's top margin would drop the second one. */
.recon-upload > .card, .recon-upload > * { margin-top: 0; }
.recon-upload-send { margin-top: 12px; justify-content: flex-end; }
.recon-file-state {
  margin: 0; padding: 10px 12px; border: 1px solid var(--border-subtle);
  font-size: var(--fs-sm); color: var(--text-muted);
}
.recon-panel { padding: 14px; border: 1px solid var(--border-subtle); background: var(--surface-sunken); }
.recon-panel > * + * { margin-top: 10px; }
.recon-range { display: grid; gap: 12px; grid-template-columns: repeat(2, minmax(0, 220px)); }
.recon-info { margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.recon-output-note {
  margin: 0; padding: 12px; border: 1px solid var(--border-subtle); background: var(--surface-sunken);
  font-size: var(--fs-sm); color: var(--text-secondary);
}
.recon-toolbar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; }
.recon-tools { flex-wrap: wrap; gap: 10px; align-items: center; }
.recon-filter { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.recon-filter .field { min-width: 170px; }
.recon-detail-title { margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.recon-detail-file { color: var(--text-muted); }
.table td.recon-note, .table th.recon-note { white-space: normal; min-width: 240px; }
@media (max-width: 820px) {
  .recon-upload, .recon-range { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Review fixes, 2026-10-12 (2.10.2)
   ========================================================================== */

/*
 * A ROW'S BUTTONS ARE NEVER CUT OFF. A classless form is a grid whose
 * children may shrink to nothing (`form:not([class]) > * { min-width: 0 }`),
 * so a table cell holding only a delete form was measured at 41px, the 106px
 * button hung out of it, and "Maddeyi sil" read "x Mad" at the card's right
 * edge - on the meeting page and the file list, at every desktop width.
 */
.table td > form:not([class]) { display: inline-grid; width: max-content; }
.table thead th.cell-actions,
.table tbody td.cell-actions { width: 1%; white-space: nowrap; text-align: right; }
.table tbody td.cell-actions > .row { justify-content: flex-end; }

/*
 * A NAME WITH NO SPACE IN IT WRAPS. One 5 000-character token made the
 * project list and the roadmap 46 000px wide. The limit is in the forms now
 * (projects/data.ts LIMITS); this is the other half: a cell that holds a name
 * may break inside a long token, and keeps a floor so that a narrow screen
 * does not stand it on end letter by letter.
 */
.table tbody td:has(> a.link),
.table tbody td.cell-text { min-width: 14ch; overflow-wrap: anywhere; }
.page-head h1,
.board-title,
.chain-item strong { overflow-wrap: anywhere; }

/*
 * THE GOAL SHEET KEEPS ITS TWO TEXT COLUMNS. Five columns of the grid have
 * fixed widths (500px together) and the goal's name and description share
 * what is left - which was 167px beside the scoring step's 340px panel on a
 * 1366 screen (one word per line) and NOTHING on a phone: both columns
 * measured 0px wide, on every step of the card.
 *
 * The sheet has a floor now and its scroller scrolls sideways under it; and
 * while the main column is too narrow for that floor, the evidence panel
 * stands below the sheet instead of beside it. The cards in that column may
 * shrink (a grid item's default floor is its content), which is what pushed
 * "Puanları kaydet" out of the right edge on a phone.
 */
.goal-grid { min-width: 920px; }
.card-split-main > * { min-width: 0; }
@media (max-width: 1700px) {
  .card-split:has(.goal-grid) { grid-template-columns: minmax(0, 1fr); }
}

/*
 * WHAT A TABLE HIDES FROM THE EYE SCROLLS WITH THE TABLE. A screen-reader
 * label (.sr-only) is taken out of the flow, and a box so placed answers to
 * its nearest POSITIONED ancestor - the sideways scroller was not one. So
 * the hidden labels of a wide table's far columns stood out on the page at
 * the column's real offset (x = 758 on a 390px phone) and the whole page
 * scrolled sideways into nothing. The scroller is their frame now.
 */
.scroll-x { position: relative; }

/*
 * A TABLE WIDER THAN ITS CARD SAYS SO. On a phone the scrollbar hides itself
 * and the last column simply ended at the card's edge, mid-word; nothing
 * said there was more. app.js marks a scroller that has more to one side
 * (`data-more`) and that edge fades out. A table that fits is not marked,
 * and a question opened inside one (`.confirm[open]`) is never faded.
 */
.scroll-x[data-more="end"] {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
  mask-image: linear-gradient(to right, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
}
.scroll-x[data-more="start"] {
  -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
  mask-image: linear-gradient(to left, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
}
.scroll-x[data-more="both"] {
  -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, .1), #000 40px, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
  mask-image: linear-gradient(to right, rgba(0, 0, 0, .1), #000 40px, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
}
.scroll-x:has(.confirm[open]) { -webkit-mask-image: none; mask-image: none; }
/* …and says it in words above the table, which the fade alone did not
   manage on a phone (components.ts scrollHint). */
.scroll-hint { display: none; margin: 0 0 6px; text-align: right; font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); }
.scroll-hint:has(+ .scroll-x[data-more]) { display: block; }
.card-flush > .scroll-hint { margin: 0; padding: 10px var(--card-p) 6px; }

/*
 * THE MONTH ON A PHONE IS AN AGENDA. Seven columns in 342px are 48px each:
 * "Haftalık Yönetim Toplantısı" stood in its cell four letters to a line.
 * Under 720px the grid folds into one column and only the days that hold
 * something (and today) are drawn, each with its weekday beside the number.
 */
.month-weekday { display: none; }
@media (max-width: 720px) {
  .month { grid-template-columns: minmax(0, 1fr); }
  .month-head,
  .month-cell-outside,
  .month-cell:not(:has(.month-entry)):not(.month-cell-today) { display: none; }
  .month-cell { min-height: 0; padding: 12px 14px; gap: 6px; }
  .month-day { font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
  .month-weekday { display: inline; color: var(--text-muted); font-weight: 400; }
  .month-entry { font-size: var(--fs-sm); padding: 7px 9px; }
  /* A month with nothing in it is already said above the card. */
  .card:has(.month-empty:not(:has(.month-cell-today))) { display: none; }
}

/*
 * THE ROADMAP ON A PHONE KEEPS ITS PROJECT IN VIEW. The timeline is the
 * page, and it began past the right edge behind three text columns, with
 * 22px months; scrolled into view, nothing said whose bar it was. The
 * project's cell stays put while the rest scrolls under it, and a month is
 * wide enough to tell from its neighbour.
 */
@media (max-width: 720px) {
  .roadmap-table thead th:first-child,
  .roadmap-table tbody td:first-child {
    position: sticky; left: 0; z-index: 1;
    min-width: 132px; max-width: 132px;
    background: var(--surface); box-shadow: 1px 0 0 var(--border);
  }
  /* Every header cell is already pinned to the top at this level; the
     corner one has to stand above its neighbours as they pass under it. */
  .roadmap-table thead th:first-child { z-index: 2; }
  /* The pinned column is the left edge: only the far side fades. */
  .scroll-x:has(.roadmap-table)[data-more="both"] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
    mask-image: linear-gradient(to right, #000 calc(100% - 40px), rgba(0, 0, 0, .1));
  }
  .scroll-x:has(.roadmap-table)[data-more="start"] { -webkit-mask-image: none; mask-image: none; }
  .table thead th.roadmap-month,
  .table tbody td.roadmap-month { min-width: 34px; }
  .table thead th.roadmap-month { font-size: var(--fs-2xs); }
}

/*
 * A SUM IS NOT BROKEN FROM ITS UNIT. In a five-tile strip a tile is 193px on
 * a 1366 screen, and "12,70 Milyar ₺" at 25px needs more: the ₺ stood alone
 * on a second line (Hacim reports). The amount holds together, and the five
 * narrow tiles set their value one size down while they are that narrow.
 */
.metric .value .money { white-space: nowrap; }
@media (min-width: 1281px) and (max-width: 1560px) {
  .metrics:has(> :nth-child(5):last-child) .metric .value { font-size: 21px; }
}
/* ...and under 1280 five in a row leave an amount no room at any size: the
   strip goes three over two there, as it already did under 1100. */
@media (max-width: 1280px) and (min-width: 761px) {
  .metrics:has(> :nth-child(5):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) and (min-width: 561px) {
  .metrics:has(> :nth-child(5):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/*
 * A RELEASE'S NAME GETS ITS OWN LINE ON A PHONE. Between the version tag and
 * a date that keeps 8.5em, the name was left about nine characters a line -
 * four lines of title, the "in use" badge pressed against the last one. The
 * tag and the date share the first line there; the name has the second.
 */
@media (max-width: 720px) {
  .release-sum { row-gap: 6px; }
  .release-sum-meta { order: 1; }
  .release-name { order: 2; flex: 1 1 100%; line-height: 1.45; }
  .release-date { min-width: 0; }
}

/* A summary that runs to a second line keeps air above and below it. With no
   vertical padding the text of a wrapped title touched both edges of its
   row; a one-line summary is still exactly as tall as before (42px). */
.disclosure summary { padding-block: 8px; }

/*
 * A FINGER NEEDS MORE THAN A LINE OF TEXT. A name in a table row is the way
 * into its record and was 17px tall on a phone; the coin and the page-guide
 * links 22px. Where the pointer is a finger their touch area grows to about
 * 33px. Nothing moves: an inline link's vertical padding takes no room, and
 * the two flex links give back in margin what they take in padding.
 */
@media (pointer: coarse) {
  .table td > a.link { padding-block: 8px; }
  .table td > a.coin-cell,
  a.page-guide { padding-block: 6px; margin-block: -6px; }
}

/* A LONG RECORD NAME DOES NOT PUSH THE TOP BAR'S BUTTONS OFF THE SCREEN. The
   ellipsis was a phone rule only; a project named in two hundred characters
   needs it at every width (its full name is the page's heading below). */
.topbar-title { min-width: 0; }
.topbar-title strong, .topbar-title span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ...and the account side gives up none of its own width for it: the title
   is the part that shortens. */
.topbar-user { flex: none; }

/*
 * THREE SMALL OVERFLOWS OF A 390px SCREEN, each a floor that did not know
 * how narrow a phone is (second crawl, 2026-10-12):
 *  - a release's change groups asked for 320px columns inside a 310px box;
 *  - a card's title and its actions never wrapped, so "Karşılaştırılacak
 *    göstergeler" was given 109px and "Şema" 34px beside their buttons;
 *  - a long name on the organisation chart ran out of its card.
 */
.release-groups { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
@media (max-width: 560px) {
  .card-head { flex-wrap: wrap; }
}
.card-title,
.person-card-name strong { overflow-wrap: anywhere; }
.person-card-name strong { min-width: 0; }
/* Two more of the same kind: the file boxes asked for 300px in a 296px
   card, and a setup step's status line ("24 kişide zincir kurulu · 8 ...")
   could not wrap. */
.file-drop-grid { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.task-state { min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 560px) {
  .task-state { flex: 1 1 100%; flex-wrap: wrap; margin-left: 0; }
}

/*
 * A QUESTION ASKED INSIDE A TABLE THAT ALREADY SCROLLS SIDEWAYS. To keep the
 * question from being cut off, an open one makes its table's scroll box
 * overflow freely (above) - right while the table fits its card. On a phone
 * the table does not fit: the whole of it spilled out of the card and the
 * page slid sideways under the finger that had just pressed "Sil". Where
 * app.js has marked the table as wider than its box (`data-more`), the box
 * goes on scrolling and the question is a sheet at the foot of the screen,
 * whole and in reach wherever the table stands.
 */
.scroll-x[data-more]:has(.confirm[open]) { overflow-x: auto; }
.scroll-x[data-more] .confirm-pop {
  position: fixed; z-index: 60;
  top: auto; right: 16px; bottom: 16px; left: 16px;
  width: auto; max-width: 420px; margin-inline: auto;
}

/* THE QUESTION IS ITS OWN PARAGRAPH, whatever cell it opens in. A row's
   action cell keeps its buttons on one line and to the right
   (`td.cell-actions`), and the pop inherited both: its sentence could not
   wrap, ran 120px out of its own box and scrolled the page sideways. */
.confirm-pop { white-space: normal; text-align: left; }

/* WITHOUT THE SIDE RAIL EVERY QUESTION IS THAT SHEET. The pop is 340px hung
   from its button's right edge; under a button at the left of the page half
   of it stood off the screen ("Projeyi sil", "Toplantıyı sil", Akit's
   archive) - on a phone and on a tablet alike, wherever the rail is folded
   away and the page starts at the screen's own edge. */
@media (max-width: 1100px) {
  .confirm-pop {
    position: fixed; z-index: 60;
    top: auto; right: 16px; bottom: 16px; left: 16px;
    width: auto; max-width: 420px; margin-inline: auto;
  }
  /* A sheet is not inside the table's box, so the box has no reason to let
     go of its table - with or without script. */
  .scroll-x:has(.confirm[open]) { overflow-x: auto; }
}

/* A question under a button at the LEFT of its card opens from that button's
   left edge (app.js marks it): hung from the right one it ran back over the
   side rail. */
.confirm-pop[data-side="start"] { right: auto; left: 0; }

/*
 * THE BELL (ui/notices.ts). A <details>: the panel opens without script.
 * The count is the accent, like the rail's waiting counts, and sits on the
 * bell's corner so the bell keeps its place whether there is one or none.
 */
.notify { position: relative; }
.notify > summary { list-style: none; position: relative; }
.notify > summary::-webkit-details-marker { display: none; }
.notify-count {
  position: absolute; top: 2px; right: 0; min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 9px; background: var(--accent); color: var(--text-on-accent);
  font-size: 12px; font-weight: 700; line-height: 17px; text-align: center;
}
.notify-panel {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  width: min(360px, calc(100vw - 32px));
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-overlay);
}
.notify-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; border-bottom: 1px solid var(--border);
}
.notify-readall { font-size: var(--fs-sm); background: none; border: 0; padding: 0; cursor: pointer; }
.notify-list { list-style: none; margin: 0; padding: 0; max-height: 360px; overflow-y: auto; }
.notify-list-page { max-height: none; border: 1px solid var(--border); }
.notify-item + .notify-item { border-top: 1px solid var(--border); }
.notify-open {
  display: flex; flex-direction: column; gap: 3px; width: 100%; padding: 10px 14px 10px 24px;
  background: none; border: 0; text-align: left; color: inherit; font: inherit; cursor: pointer;
  position: relative;
}
.notify-open:hover { background: var(--surface-hover); }
.notify-open:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.notify-item.is-unread .notify-open::before {
  content: ""; position: absolute; left: 10px; top: 16px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent);
}
.notify-item.is-unread .notify-text { font-weight: 600; }
.notify-text { font-size: var(--fs-sm); }
.notify-when { font-size: var(--fs-2xs); color: var(--text-muted); }
.notify-empty { padding: 14px; color: var(--text-muted); font-size: var(--fs-sm); margin: 0; }
.notify-all { display: block; padding: 10px 14px; border-top: 1px solid var(--border); font-size: var(--fs-sm); }
@media (max-width: 640px) {
  .notify-panel { position: fixed; left: 16px; right: 16px; top: 64px; width: auto; }
}

/*
 * THE LIVE STRIP (layout.ts, app.js): something this page shows changed.
 * Fixed at the foot, out of the way of what the reader is doing; it offers
 * the reload and never forces it.
 */
.live-strip {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 70;
  display: flex; align-items: center; gap: 12px; padding: 10px 12px 10px 16px;
  background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--accent);
  box-shadow: var(--shadow-overlay); font-size: var(--fs-sm); max-width: calc(100vw - 32px);
}
.live-strip[hidden] { display: none; }

/*
 * THE USERS SCREENS (routes/users.ts). A form inside a settings row keeps
 * its boxes and its button on one line, the button at the boxes' foot; every
 * action button in those rows is one width, so a column of them reads as a
 * column. The approval cell is one small-size line. The two account lists
 * share a card, each under its own heading and count.
 */
.inline-form { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.inline-form > .field { flex: 1 1 220px; min-width: 0; }
/* A button alone in its row stands in the same right-hand column as the others. */
.inline-form > .btn:only-child { margin-left: auto; }
.setting-row-control > form > .btn,
.setting-row-control > .confirm > summary,
.inline-form > .btn { min-width: 168px; }
.setting-row-control .confirm { display: inline-block; }
.decision { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.decision > form { margin: 0; }
.decision .field-bare .control { width: 120px; }
.list-head { padding: 18px 22px 10px; border-top: 1px solid var(--border-subtle); }
.list-head:first-child, .list-note + .list-head { border-top: 0; }
.list-head h3 { margin: 0; font-size: var(--fs-md); font-weight: 700; display: flex; align-items: center; gap: 8px; }
.list-head p { margin: 4px 0 0; font-size: var(--fs-xs); color: var(--text-secondary); }
.list-count {
  min-width: 22px; height: 20px; padding: 0 7px; border-radius: 10px;
  background: var(--surface-sunken); color: var(--text-secondary);
  font-size: var(--fs-2xs); font-weight: 700; line-height: 20px; text-align: center;
}
.list-note { margin: 0; padding: 12px 22px 0; font-size: var(--fs-xs); color: var(--text-secondary); }
@media (max-width: 640px) {
  .inline-form > .btn, .setting-row-control > form > .btn, .setting-row-control > .confirm > summary { width: 100%; }
  .setting-row-control .confirm { display: block; }
}

/* An account list scrolls inside its own panel (routes/users.ts); the
   table's sticky head stands at the panel's top while the rows move. */
.account-list .scroll-x { max-height: min(440px, 55vh); overflow: auto; overscroll-behavior: contain; }

/*
 * A NEW PASSWORD'S RULES (components.ts passwordChecks). Plain rules without
 * script; with it (.is-live) each line wears a mark: an empty ring before
 * anything is typed, a green tick when met, a red cross when not.
 */
.pw-checks { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 6px; font-size: var(--fs-sm); color: var(--text-secondary); }
.pw-checks li { display: flex; align-items: center; gap: 8px; }
.pw-mark {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  border: 1.5px solid var(--border); display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; line-height: 1;
}
.pw-checks:not(.is-live) .pw-mark::before { content: "•"; color: var(--text-muted); }
.pw-checks:not(.is-live) .pw-mark { border: 0; }
.pw-checks li.is-ok { color: var(--ok-text, var(--ok)); }
.pw-checks li.is-ok .pw-mark { border-color: var(--ok); background: var(--ok); color: var(--surface); }
.pw-checks li.is-ok .pw-mark::before { content: "✓"; }
.pw-checks li.is-bad { color: var(--error-text); }
.pw-checks li.is-bad .pw-mark { border-color: var(--border-danger); color: var(--error-text); }
.pw-checks li.is-bad .pw-mark::before { content: "✕"; }

/*
 * NOTICES (ui/notices.ts), the bell and the page. Every notice wears its
 * kind: a tinted icon (card, account, support, peer) and a word. Unread ones
 * carry the accent bar on their left edge and stand above the read ones.
 */
.bell-icon {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-sunken); color: var(--text-secondary);
}
.bell-icon.tone-card    { background: var(--accent-tint, var(--surface-selected)); color: var(--accent); }
.bell-icon.tone-account { background: var(--warn-tint, var(--surface-sunken)); color: var(--warn-text, var(--text-body)); }
.bell-icon.tone-support { background: var(--info-tint, var(--surface-sunken)); color: var(--info-text, var(--text-body)); }
.bell-icon.tone-peer    { background: var(--ok-tint); color: var(--ok-text); }

/* The bell's lines: icon, sentence, kind and time; no dot, the bar marks unread. */
.notify-open { flex-direction: row !important; align-items: flex-start; gap: 10px; padding: 10px 14px !important; }
.notify-item.is-unread .notify-open::before { content: none !important; }
.notify-item.is-unread .notify-open { box-shadow: inset 3px 0 0 var(--accent); background: var(--surface-selected); }
.notify-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* The page. */
.bell-section + .bell-section { margin-top: 26px; }
.bell-section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.bell-section-head h2 { margin: 0; font-size: var(--fs-md); font-weight: 700; display: flex; align-items: center; gap: 8px; }
.bell-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); overflow: hidden; }
.bell-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 14px; align-items: center;
  padding: 14px 16px; background: var(--surface);
}
.bell-row + .bell-row { border-top: 1px solid var(--border-subtle); }
.bell-row.is-unread { box-shadow: inset 3px 0 0 var(--accent); background: var(--surface-selected); }
.bell-body p { margin: 0; }
.bell-meta { font-size: var(--fs-2xs); color: var(--text-muted); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.bell-kind { font-weight: 700; color: var(--text-secondary); }
.bell-new { margin-left: 4px; padding: 1px 6px; border-radius: var(--radius-sm); background: var(--accent-tint); color: var(--accent-text); font-weight: 700; letter-spacing: .04em; }
.bell-title { margin-top: 3px !important; font-size: var(--fs-sm); font-weight: 600; color: var(--text-body); }
.bell-row:not(.is-unread) .bell-title { font-weight: 500; }
.bell-hint { margin-top: 2px !important; font-size: var(--fs-xs); color: var(--text-secondary); }
.bell-section.is-read .bell-row { opacity: .85; }
.bell-day { margin: 14px 0 8px; font-size: var(--fs-xs); color: var(--text-muted); }
.bell-go { margin: 0; }
.bell-kept { margin-top: 16px; }
@media (max-width: 640px) {
  .bell-row { grid-template-columns: auto minmax(0, 1fr); }
  .bell-go { grid-column: 2; }
}

/* The notices page: filters, a bar that stays, the list scrolling under it. */
.bell-filters { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; margin-bottom: 14px; }
.bell-panel { border: 1px solid var(--border); }
.bell-toolbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--surface-sunken);
  font-size: var(--fs-sm);
}
.bell-toolbar-gap { flex: 1; }
.bell-picked { color: var(--text-secondary); }
.bell-scroll { height: min(560px, 62vh); overflow-y: auto; overscroll-behavior: contain; padding: 0 14px 14px; }
.bell-scroll .bell-list { border: 1px solid var(--border-subtle); }
.bell-row { grid-template-columns: auto auto minmax(0, 1fr) auto; }
.bell-pick { display: inline-flex; align-items: center; cursor: pointer; }
@media (max-width: 640px) {
  .bell-row { grid-template-columns: auto auto minmax(0, 1fr); }
  .bell-row > .btn { grid-column: 3; justify-self: start; }
}

/* -- destek talepleri: liste ve yazisma (ui/support-panel.ts) ------------- */

/* Liste: bir mesajlasma uygulamasinin sohbet listesi gibi. Satirin tamami baglanti. */
.sup-list { list-style: none; margin: 0; padding: 0; }
.sup-item + .sup-item { border-top: 1px solid var(--border-subtle); }
.sup-item-link {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; align-items: start;
  padding: 12px 14px; color: inherit; text-decoration: none;
}
.sup-item-link:hover { background: var(--surface-row-hover, var(--surface-hover)); text-decoration: none; }
.sup-item.is-current .sup-item-link { background: var(--surface-selected); box-shadow: inset 3px 0 0 var(--accent); }
.sup-item-icon {
  width: 36px; height: 36px; display: inline-grid; place-items: center; flex: none;
  border-radius: var(--radius-full); background: var(--surface-sunken); color: var(--text-secondary);
}
.sup-item-main { display: grid; gap: 4px; min-width: 0; }
.sup-item-top { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.sup-item-subject { flex: 1; min-width: 0; font-weight: 600; font-size: var(--fs-sm); color: var(--text-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sup-item.is-unread .sup-item-subject { font-weight: 800; }
.sup-item-time { flex: none; font-size: var(--fs-2xs); color: var(--text-muted); }
.sup-item.is-unread .sup-item-time { color: var(--accent-text); font-weight: 700; }
.sup-item-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--fs-2xs); color: var(--text-muted); }
.sup-item-reporter { font-weight: 600; color: var(--text-secondary); }
.sup-item-last {
  font-size: var(--fs-xs); color: var(--text-secondary); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
}
.sup-item-last b { font-weight: 600; color: var(--text-body); }
.sup-item-files { display: inline-flex; align-items: center; gap: 2px; margin-left: 6px; color: var(--text-muted); vertical-align: middle; }
.sup-item-unread {
  align-self: center; min-width: 22px; height: 22px; padding: 0 7px; display: inline-grid; place-items: center;
  border-radius: var(--radius-full); background: var(--accent-solid); color: var(--text-on-accent);
  font-size: var(--fs-2xs); font-weight: 800; font-variant-numeric: tabular-nums;
}
.sup-list-compact .sup-item-link { padding: 10px 12px; gap: 10px; }
.sup-list-compact .sup-item-icon { width: 30px; height: 30px; }
.sup-list-compact .sup-item-last { -webkit-line-clamp: 1; }

/* Kaydirilan panel: liste uzadikca sayfa degil panel kayar. Kuyrukta yukseklik
   sabit: suzgec degisince alttaki sayfa oynamaz. */
.sup-scroll { max-height: min(640px, 66vh); overflow-y: auto; overscroll-behavior: contain; }
.sup-scroll-fixed { height: min(640px, 66vh); max-height: none; }

/* Suzgecler */
.sup-filters { display: grid; gap: 12px; margin-bottom: 14px; }
.sup-count { margin-left: 4px; opacity: .75; font-size: var(--fs-2xs); }
.sup-filter a[aria-current="page"] .sup-count { opacity: 1; }
.sup-kinds { display: flex; flex-wrap: wrap; gap: 6px; }
.sup-kind {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px;
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: var(--fs-xs); color: var(--text-secondary); text-decoration: none; background: var(--surface);
}
.sup-kind:hover { border-color: var(--border-hover); text-decoration: none; }
.sup-kind[aria-current="page"] { background: var(--surface-sunken); border-color: var(--text-secondary); color: var(--text-body); font-weight: 700; }
.sup-kind .num { color: var(--text-muted); }
.sup-search { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.sup-search-box {
  flex: 1 1 260px; max-width: 420px; display: flex; align-items: center; gap: 8px; padding: 0 10px;
  border: 1px solid var(--border-input); border-radius: var(--radius); background: var(--surface); color: var(--text-muted);
  height: var(--control-h-sm, 32px);
}
.sup-search-box:focus-within { box-shadow: var(--focus-ring); border-color: var(--accent); }
.sup-search-box input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--text-body); font: inherit; font-size: var(--fs-sm); }
.sup-search-box input::-webkit-search-cancel-button { display: none; }

/* Yeni talep: tek dugmenin altinda katlanir. */
.sup-new > summary { list-style: none; display: inline-flex; width: auto; }
.sup-new > summary::-webkit-details-marker { display: none; }
.sup-new[open] > summary { margin-bottom: var(--rhythm); }
.sup-new-form { gap: 16px; }
.sup-cats { border: 0; margin: 0; padding: 0; min-width: 0; }
.sup-cats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px; margin-top: 6px; }
.sup-cat {
  position: relative; display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface);
}
.sup-cat:hover { border-color: var(--border-hover); }
.sup-cat input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.sup-cat:has(input:checked) { border-color: var(--accent); background: var(--surface-selected); box-shadow: inset 0 0 0 1px var(--accent); }
.sup-cat:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.sup-cat-text { display: grid; gap: 2px; }
.sup-cat-label { font-weight: 700; font-size: var(--fs-sm); color: var(--text-body); }
.sup-cat-hint { font-size: var(--fs-2xs); color: var(--text-muted); line-height: 1.4; }
.sup-cat-chip { display: inline-flex; align-items: center; gap: 4px; color: var(--text-secondary); }
.sup-attach { display: grid; gap: 6px; justify-items: start; }
.sup-attach.is-over, .tk-composer.is-over { outline: 2px dashed var(--accent); outline-offset: 2px; }

/* Talep sayfasi: genis ekranda solda liste, sagda yazisma. */
.sup-layout {
  --tk-h: max(460px, calc(100dvh - 150px));
  display: grid; grid-template-columns: minmax(250px, 320px) minmax(0, 1fr); gap: 16px; align-items: start;
}
.sup-side { border: 1px solid var(--border); background: var(--surface); display: flex; flex-direction: column; height: var(--tk-h); }
.sup-side-head { padding: 12px 14px; border-bottom: 1px solid var(--border-subtle); font-weight: 700; font-size: var(--fs-sm); background: var(--surface-band-head); }
.sup-side-head a { color: var(--text-body); }
.sup-side-list { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.sup-side-list .sup-list { border: 0; }
.sup-side-list > .card-note { padding: 14px; }
@media (max-width: 1100px) {
  .sup-layout { grid-template-columns: minmax(0, 1fr); }
  .sup-side { display: none; }
}

/* Yazisma */
.tk { display: flex; flex-direction: column; height: var(--tk-h); min-width: 0; border: 1px solid var(--border); background: var(--surface); }
.tk-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 12px 16px;
  border-bottom: 1px solid var(--border-subtle); background: var(--surface-band-head);
}
.tk-back { display: inline-grid; place-items: center; width: 34px; height: 34px; color: var(--text-secondary); border-radius: var(--radius); }
.tk-back:hover { background: var(--surface-hover); text-decoration: none; }
.tk-title { flex: 1 1 260px; min-width: 0; display: grid; gap: 3px; }
.tk-title h1 { margin: 0; font-size: var(--fs-lg); font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.tk-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--text-muted); }
.tk-state { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tk-moves { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }

.tk-log {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  list-style: none; margin: 0; padding: 16px 18px;
  display: flex; flex-direction: column; gap: 6px;
  background: var(--surface-sunken);
}
.tk-day, .tk-sys { align-self: center; text-align: center; margin: 8px 0 4px; }
.tk-day span {
  display: inline-block; padding: 2px 10px; border-radius: var(--radius);
  background: var(--surface);
  font-size: var(--fs-2xs); font-weight: 600; color: var(--text-secondary);
}
.tk-sys span { display: inline-block; font-size: var(--fs-2xs); color: var(--text-muted); padding: 2px 10px; }
.tk-msg { display: flex; }
.tk-msg.is-mine { justify-content: flex-end; }
.tk-bubble {
  position: relative; max-width: min(78%, 620px); padding: 7px 11px 6px;
  background: var(--surface); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg);
}
.tk-msg.is-mine .tk-bubble { background: var(--surface-selected); border-color: color-mix(in srgb, var(--accent) 18%, var(--border-subtle)); }
/* Ic not SARI ve sozle isaretli: kisinin gormedigi bir satir siradan gorunmemeli. */
.tk-msg.is-internal .tk-bubble { background: var(--warn-tint); border-color: transparent; box-shadow: inset 3px 0 0 var(--warn); }
.tk-who { display: block; font-size: var(--fs-2xs); font-weight: 700; color: var(--text-secondary); margin-bottom: 2px; }
.tk-who-internal { display: flex; align-items: center; gap: 4px; color: var(--warn-text); }
.tk-text { margin: 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-body); white-space: pre-wrap; overflow-wrap: anywhere; }
.tk-time { display: block; text-align: right; margin-top: 2px; font-size: 12px; color: var(--text-muted); }
.tk-pics { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
.tk-pic { display: block; border: 1px solid var(--border-subtle); background: var(--surface); line-height: 0; overflow: hidden; }
.tk-pic img { display: block; width: auto; height: 160px; max-width: min(320px, 100%); object-fit: cover; }
.tk-file {
  display: flex; align-items: center; gap: 8px; margin: 6px 0 2px; padding: 8px 10px; max-width: 360px;
  background: var(--surface); border: 1px solid var(--border-subtle); color: var(--text-body); text-decoration: none;
}
.tk-file:hover { border-color: var(--border-hover); text-decoration: none; }
.tk-file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-xs); font-weight: 600; }
.tk-file-size { font-size: var(--fs-2xs); color: var(--text-muted); }
.tk-end { height: 0; }

.tk-closed { padding: 14px 16px; border-top: 1px solid var(--border-subtle); color: var(--text-secondary); font-size: var(--fs-sm); display: grid; gap: 10px; }
.tk-closed > p { margin: 0; display: flex; align-items: center; gap: 8px; }
.tk-closed .tk-input { width: 100%; }
.tk-composer { border-top: 1px solid var(--border-subtle); padding: 10px 12px 8px; background: var(--surface); display: grid; gap: 6px; }
.tk-mode { border: 0; margin: 0; padding: 0; display: inline-flex; justify-self: start; }
.tk-mode label { cursor: pointer; position: relative; }
.tk-mode input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.tk-mode span {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; font-size: var(--fs-xs); font-weight: 600;
  border: 1px solid var(--border); color: var(--text-secondary); background: var(--surface);
}
.tk-mode label + label span { border-left: 0; }
.tk-mode label:first-of-type span { border-radius: var(--radius) 0 0 var(--radius); }
.tk-mode label:last-of-type span { border-radius: 0 var(--radius) var(--radius) 0; }
.tk-mode input:checked + span { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--text-on-accent); }
.tk-mode .tk-mode-internal input:checked + span { background: var(--warn); border-color: var(--warn); color: #1d1503; }
.tk-mode input:focus-visible + span { box-shadow: var(--focus-ring); }
.tk-mode input:disabled + span { opacity: .45; cursor: not-allowed; }
.tk-internal-warn { display: none; margin: 0; font-size: var(--fs-xs); color: var(--warn-text); align-items: center; gap: 5px; }
.tk-composer:has(input[name="as"][value="internal"]:checked) { background: var(--warn-tint); }
.tk-composer:has(input[name="as"][value="internal"]:checked) .tk-internal-warn { display: flex; }
.tk-composer:has(input[name="as"][value="internal"]:checked) .tk-input { border-color: var(--warn); }
.tk-row { display: flex; align-items: flex-end; gap: 8px; }
.tk-attach, .tk-send {
  flex: none; width: 42px; height: 42px; display: inline-grid; place-items: center; cursor: pointer;
  border-radius: var(--radius); border: 0;
}
.tk-attach { color: var(--text-secondary); background: transparent; }
.tk-attach:hover { background: var(--surface-hover); }
.tk-composer:has(input[type="file"]:focus-visible) .tk-attach { box-shadow: var(--focus-ring); }
.tk-send { background: var(--accent-solid); color: var(--text-on-accent); }
.tk-send:hover { filter: brightness(1.08); }
.tk-send:focus-visible { box-shadow: var(--focus-ring); outline: 0; }
.tk-input {
  flex: 1; min-width: 0; resize: none; min-height: 42px; max-height: 180px; padding: 10px 14px;
  border: 1px solid var(--border-input); border-radius: var(--radius); background: var(--surface); color: var(--text-body);
  font: inherit; font-size: var(--fs-sm); line-height: 1.45;
}
.tk-input:focus { outline: 0; border-color: var(--accent); box-shadow: var(--focus-ring); }
.tk-hint { margin: 0; font-size: var(--fs-2xs); color: var(--text-muted); padding-left: 50px; }
.tk-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.tk-chips:empty { display: none; }
.tk-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 260px; padding: 3px 4px 3px 8px;
  border: 1px solid var(--border); background: var(--surface-sunken); font-size: var(--fs-xs);
}
.tk-chip img { width: 28px; height: 28px; object-fit: cover; }
.tk-chip-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-chip-size { color: var(--text-muted); font-size: var(--fs-2xs); }
.tk-chip button { border: 0; background: none; cursor: pointer; color: var(--text-muted); width: 24px; height: 24px; display: inline-grid; place-items: center; }
.tk-chip button:hover { color: var(--error-text); }
.tk-composer .field-error, .sup-attach .field-error { margin: 0; }

@media (max-width: 760px) {
  /* The phone's two bars above (the menu and the title) take about 210 px. */
  .sup-layout { --tk-h: max(400px, calc(100dvh - 240px)); }
  .tk-head { padding: 8px 10px; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 8px; }
  .tk-title h1 { font-size: var(--fs-md); }
  .tk-state { grid-column: 1 / -1; }
  .tk-log { padding: 12px 10px; }
  .tk-bubble { max-width: 88%; }
  .tk-hint { display: none; }
  .tk-pic img { height: 120px; }
}

/* -- kose dili: her yerde hafif yuvarlak ------------------------------------ */

/*
 * ONE RULE FOR EVERY CORNER. What is clicked or typed in (buttons, boxes,
 * badges) takes `--radius`; what holds things (cards, panels, pop-ups,
 * toasts) takes `--radius-lg`; only avatars, icon discs, dots and counts are
 * round. A new panel joins the list below rather than writing its own number.
 */
.page-head, .card, .metric, .section-body > .filters, .status, .tile, .board-tools, .board-card,
.status-item, .toast, .board-cardless, .context-aside, .edit-frame, .picker-tab, .step-tracker,
.js .viewer[open] > .viewer-panel, .ctr-page, .manual-toc, .manual-shot-frame, .pick, .ranked-list,
.date-step-card, .confirm-pop, .live-progress, .notify-panel, .live-strip, .empty,
.bell-panel, .sup-side, .tk, dialog, .combo-list {
  border-radius: var(--radius-lg);
}
.chain-strip .person-chip, .queue-row, .tagged-item, .bell-list, .sup-list, .sup-cat, .tk-file, .tk-pic, .tk-chip,
.combo-option {
  border-radius: var(--radius);
}

/* The hero's left bar was a border-image, and a border-image cannot follow a
   rounded corner: drawn as a background strip instead, the same fade. */
.page-head {
  border-left: 0; border-image: none;
  /* A browser without color-mix() drops the faded bar below and keeps this solid one. */
  background-image: linear-gradient(var(--accent), var(--accent));
  background-image: linear-gradient(
    180deg,
    var(--accent) 0%,
    var(--accent) 34%,
    color-mix(in srgb, var(--accent) 22%, transparent) 78%,
    transparent 100%
  );
  background-size: 4px 100%; background-repeat: no-repeat; background-position: left top;
}

/* A row of joined buttons is ONE control: rounded at its two ends only. */
.segmented > a, .segmented > button { border-radius: 0; }
.segmented > :first-child { border-top-left-radius: var(--radius); border-bottom-left-radius: var(--radius); }
.segmented > :last-child { border-top-right-radius: var(--radius); border-bottom-right-radius: var(--radius); }
/* Panels whose rows have their own backgrounds keep them inside the corners. */
.notify-panel, .bell-panel, .sup-side { overflow: hidden; }
/* The conversation is NOT clipped: on a small phone a box with five files and
   a long message can be taller than the room left, and a clipped send button
   cannot be reached. Its two ends take the corners instead. */
.tk-head { border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
.tk-composer, .tk-closed { border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
.tk-log { min-height: 140px; }
.tk-chips { max-height: 72px; overflow-y: auto; }
@media (max-width: 760px) { .tk-input { max-height: 120px; } }

/* The rest of the application's boxes, under the same rule (found by listing
   every fully bordered rule that had no corner of its own). */
.section-body > .scroll-x, .main > .filters, .period-switch, .tile-flat, .panel-note, .phase-strip li,
.disclosure, .key-points, .stat-band, .figure-card, .outcome, .link-card, .picture, .picture-sample,
.placeholder-note, .contents-top, .contents-rail, .fact-row, .action-row, .row-list-item, .form-column,
.markup-toolbar, .file-drop-preview, .goal-pick-wait, .pane-scroll, .pick-tile, .code-block,
.mode-switch, .acc-actions-bar, .ctr-band, .ctr-tools, .manual-fact, .manual-figure, .manual-defs,
.health-gap-list, .tree-node, .release-now, .radio-option, .choice-option, .mini-ui, .filepick, .msg,
.file-drop, .margin-note > summary, .margin-note-body, .plan-list, .file-list, .notice-row, .pick-card,
.recon-file-state, .recon-panel, .recon-output-note, .notify-list-page {
  border-radius: var(--radius-lg);
}
.font-chip, .board-fold-btn, .target-track, .queue-go, .badge-late, .topbar-count, .tagged-tag,
.outcome-badge, .part-heading-tag, .computed-line, .order-row, .order-badge, .picker-tab-add,
.markup-swatch, .queue-group-count, .pick-tile-rank, .release-version, .release-list code, .theme-chip,
.accent-chip, .mini-font, .mini-hero, .mini-arrive, .file-drop-icon, .change-steps a, .ctr-marker,
.check-chip, .day-chips span, .mark-chip, .usage-meter, .ctr-obj {
  border-radius: var(--radius);
}
.mode-switch, .plan-list, .file-list, .disclosure { overflow: hidden; }
/* Numbered steps: the number sits in a small soft square, like a badge. */
.task-row::before, .guide-index a::before { border-radius: var(--radius-sm); }
/* A count kept on the page for the script to fill, hidden at zero. */
.sidebar-count[hidden] { display: none; }
/* A clipped panel draws its focus ring inside, where the clip cannot cut it. */
.disclosure > summary:focus-visible, .mode-switch :focus-visible { outline-offset: -2px; }

/* -- organizasyon semasi: uc gorunum (performance/org-views.ts) ----------- */

.org-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 14px; }
.org-search { display: flex; align-items: center; gap: 10px; flex: 1 1 300px; flex-wrap: wrap; }
.org-search[hidden], .oc-tools[hidden], [data-org-hint][hidden] { display: none; }
.org-bar .segmented a { gap: 6px; }
.oc-you { font-style: normal; margin-left: 6px; padding: 0 6px; border-radius: var(--radius-sm); background: var(--accent-tint); color: var(--accent-text); font-size: var(--fs-2xs); font-weight: 700; }
.oc-note { display: flex; align-items: center; gap: 4px; margin-top: 2px; font-size: var(--fs-2xs); color: var(--warn-text); }
[data-org-name].is-match { background: var(--warn-tint); box-shadow: inset 0 0 0 2px var(--warn); }
[data-org-name].is-found { outline: 3px solid var(--accent); outline-offset: 3px; }

/* ŞEMA — the canvas. Without script it is a box that scrolls both ways; with
   it (.is-live) the stage is moved and scaled by app.js orgCanvas. */
.oc { --oc-line: var(--border-hover); display: grid; gap: 8px; }
.oc-tools { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* The zoom's − and + as tall as "Tamamını sığdır" beside them (a small icon button is 28px). */
.oc-tools .btn-icon, .oc-tools .btn-icon.btn-sm { width: var(--control-h-sm); height: var(--control-h-sm); justify-content: center; font-size: var(--fs-md); font-weight: 700; }
.oc-zoom { min-width: 48px; text-align: center; font-size: var(--fs-xs); color: var(--text-secondary); }
.oc-viewport {
  position: relative; height: min(720px, 74vh); overflow: auto;
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background-color: var(--surface-sunken);
  background-image: radial-gradient(circle, color-mix(in srgb, var(--text-muted) 30%, transparent) 1px, transparent 1.4px);
  background-size: 22px 22px;
}
.oc-viewport:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.oc-viewport.is-live { overflow: hidden; cursor: grab; touch-action: none; user-select: none; }
.oc-viewport.is-dragging { cursor: grabbing; }
.oc-stage { display: inline-block; min-width: 100%; padding: 32px 40px 48px; transform-origin: 0 0; }
.oc-viewport.is-live .oc-stage { position: absolute; top: 0; left: 0; min-width: 0; will-change: transform; }

.oc-tree, .oc-level, .oc-stack { list-style: none; margin: 0; padding: 0; }
.oc-tree { display: flex; justify-content: center; gap: 24px; }
.oc-item { position: relative; display: flex; flex-direction: column; align-items: center; }
.oc-level { position: relative; display: flex; justify-content: center; padding-top: 22px; }
.oc-level > .oc-item { padding: 22px 10px 0; }

/* The joining lines: a bar over each row of children, a drop to each. */
.oc-level::before { content: ""; position: absolute; top: 0; left: 50%; height: 22px; border-left: 2px solid var(--oc-line); }
.oc-level > .oc-item::before, .oc-level > .oc-item::after {
  content: ""; position: absolute; top: 0; width: 50%; height: 22px; border-top: 2px solid var(--oc-line);
}
.oc-level > .oc-item::before { right: 50%; }
.oc-level > .oc-item::after { left: 50%; border-left: 2px solid var(--oc-line); }
.oc-level > .oc-item:first-child::before { border-top: 0; }
/* The last one's drop is its ::before's curved right edge: its own straight drop would draw a second line beside it. */
.oc-level > .oc-item:last-child::after { border: 0; }
.oc-level > .oc-item:last-child::before { border-right: 2px solid var(--oc-line); border-top-right-radius: 10px; }
.oc-level > .oc-item:first-child::after { border-top-left-radius: 10px; }
.oc-level > .oc-item:only-child { padding-top: 0; }
.oc-level > .oc-item:only-child::before, .oc-level > .oc-item:only-child::after { display: none; }

/* People who lead nobody: one column under their manager, on one line. */
.oc-stack { position: relative; display: flex; flex-direction: column; align-items: center; gap: 10px; padding-top: 22px; }
.oc-stack::before { content: ""; position: absolute; top: 0; bottom: 24px; left: 50%; border-left: 2px solid var(--oc-line); }
.oc-group > .oc-stack { padding-top: 0; }

.oc-kids { display: flex; flex-direction: column; align-items: center; }
.oc-kids[class*="tone-"] { --oc-line: color-mix(in srgb, var(--tone) 60%, var(--border)); }
.oc-toggle {
  position: relative; z-index: 1; margin-top: 14px; list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 3px; padding: 2px 9px;
  border-radius: var(--radius-full); border: 2px solid var(--oc-line); background: var(--surface);
  font-size: var(--fs-2xs); font-weight: 700; color: var(--text-body);
}
.oc-toggle::-webkit-details-marker { display: none; }
.oc-toggle::before { content: ""; position: absolute; bottom: calc(100% + 2px); left: 50%; height: 14px; border-left: 2px solid var(--oc-line); }
.oc-toggle svg { transition: transform var(--speed); }
.oc-kids:not([open]) > .oc-toggle svg { transform: rotate(-90deg); }
.oc-kids:not([open]) > .oc-toggle { background: var(--oc-line); color: var(--surface); }
.oc-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.oc-card {
  position: relative; z-index: 1; width: 224px; display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; text-align: left; cursor: default;
  background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--tone, var(--border));
  border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
}
.oc-card-text { display: flex; flex-direction: column; min-width: 0; }
.oc-card strong { font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); overflow-wrap: anywhere; }
.oc-role { font-size: var(--fs-xs); color: var(--text-secondary); line-height: 1.35; }
.oc-meta { font-size: var(--fs-2xs); color: var(--text-muted); }
.oc-card.is-self { box-shadow: 0 0 0 2px var(--accent), var(--shadow-card); }
.oc-card.has-note { border-color: var(--warn); }
.oc-board { width: auto; align-items: center; border-top-color: var(--text-secondary); color: var(--text-secondary); }

/* LİSTE — compact rows; a team in a frame of its manager's colour. */
.ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.ol-branch > summary { list-style: none; cursor: pointer; }
.ol-branch > summary::-webkit-details-marker { display: none; }
.ol-row {
  display: flex; align-items: center; gap: 10px; padding: 7px 12px;
  background: var(--surface); border: 1px solid var(--border-subtle); border-radius: var(--radius);
}
.ol-branch > summary:hover .ol-row { border-color: var(--border-hover); }
.ol-branch > summary:focus-visible { outline: none; }
.ol-branch > summary:focus-visible .ol-row { box-shadow: var(--focus-ring); }
.ol-row > .icon:first-child { flex: none; color: var(--text-icon); transition: transform var(--speed); }
.ol-branch[open] > summary .ol-row > .icon:first-child { transform: rotate(90deg); }
.ol-spacer { flex: none; width: 14px; }
.ol-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ol-name { display: flex; align-items: center; flex-wrap: wrap; }
.ol-name strong { font-size: var(--fs-sm); font-weight: 600; color: var(--text-body); }
.ol-role { font-size: var(--fs-xs); color: var(--text-muted); }
.ol-row.is-self { border-color: var(--accent); }
.ol-count {
  margin-left: auto; flex: none; padding: 2px 9px; border-radius: var(--radius-full);
  border: 1px solid color-mix(in srgb, var(--tone) 55%, transparent);
  background: color-mix(in srgb, var(--tone) 14%, transparent);
  font-size: var(--fs-2xs); font-weight: 700; color: var(--text-body); white-space: nowrap;
}
.ol-team {
  margin: 6px 0 6px 20px; padding: 8px 10px 10px 12px;
  border-left: 3px solid var(--tone);
  background: color-mix(in srgb, var(--tone) 6%, transparent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.ol-team-head { margin: 0 0 6px; font-size: var(--fs-2xs); font-weight: 700; color: var(--text-secondary); }

/* EKİPLER — one card per department. */
/* A grid, so the cards of a row stand level, top and bottom; a long
   department scrolls inside its card instead of stretching the row. */
.og-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; align-items: stretch; }
.og-dept {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--tone);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
}
.og-head { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--border-subtle); }
.og-head h3 { margin: 0; flex: 1; min-width: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--text-body); }
.og-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--tone); }
.og-n { flex: none; font-size: var(--fs-2xs); color: var(--text-muted); }
.og-people { list-style: none; margin: 0; padding: 8px 10px 12px; max-height: 460px; overflow-y: auto; flex: 1; }
.og-people, .og-sub { --og-line: color-mix(in srgb, var(--tone) 55%, var(--border)); }
.og-item { position: relative; list-style: none; }
.og-person { display: flex; gap: 10px; align-items: flex-start; padding: 6px; border-radius: var(--radius); }
.og-person.is-self { background: var(--surface-selected); }
/* The tree's lines: a spine down from the manager's mark, an elbow to each of their people. */
.og-sub { margin: 0 0 0 20px; padding: 0; }
.og-sub > .og-item { padding-left: 16px; }
.og-sub > .og-item::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; border-left: 2px solid var(--og-line); }
.og-sub > .og-item::after { content: ""; position: absolute; left: 0; top: 20px; width: 14px; border-top: 2px solid var(--og-line); }
.og-sub > .og-item:last-child::before { bottom: auto; height: 20px; width: 14px; border-bottom: 2px solid var(--og-line); border-bottom-left-radius: 8px; }
.og-sub > .og-item:last-child::after { display: none; }
/* The view switch, the filters and the search: one row, one height. */
.org-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.org-filters .field { margin: 0; }
.org-filters .control { height: 34px; min-height: 34px; padding-top: 0; padding-bottom: 0; width: auto; max-width: 240px; font-size: var(--fs-xs); }
.org-filters .btn { height: 34px; }
.org-bar .sup-search-box { height: 34px; }
/* A picked title: its people stand out, everybody else steps back. */
.org-pick-note { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; padding: 8px 12px; border-radius: var(--radius); background: var(--warn-tint); color: var(--text-body); font-size: var(--fs-sm); }
.org-pick-note a { margin-left: auto; font-weight: 600; }
[data-org-picking] [data-org-name]:not([data-org-pick]) { opacity: .38; }
[data-org-picking] [data-org-pick] { box-shadow: 0 0 0 2px var(--warn); }
.oc-name { display: flex; align-items: center; flex-wrap: wrap; gap: 0 2px; }
.org-search-count { flex: none; font-size: var(--fs-2xs); color: var(--text-muted); white-space: nowrap; }
.org-search-count:empty { display: none; }
/* A user's roles explained under the boxes; a page choice that lowers the role, said in the warning colour. */
.role-legend { margin: 12px 0 4px; display: grid; gap: 6px; padding: 12px 14px; border-radius: var(--radius); background: var(--surface-sunken); }
.role-legend > div { display: grid; grid-template-columns: 120px 1fr; gap: 10px; font-size: var(--fs-sm); }
.role-legend dt { font-weight: 700; color: var(--text-body); }
.role-legend dd { margin: 0; color: var(--text-secondary); }
.page-warn { display: block; color: var(--warn-text); font-weight: 600; }
.page-warn[hidden] { display: none; }
@media (max-width: 560px) { .role-legend > div { grid-template-columns: 1fr; gap: 2px; } }

/* -- a date in Turkish: the box, its calendar button and the calendar (app.js dateFields) -- */
.control[data-date-field] { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.date-wrap { position: relative; display: flex; align-items: stretch; width: 100%; max-width: 15em; }
.date-wrap > .control { flex: 1; min-width: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; }
.date-pick {
  flex: none; width: 42px; display: inline-grid; place-items: center; cursor: pointer;
  border: 1px solid var(--border-input); border-left: 0; background: var(--surface); color: var(--text-secondary);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.date-pick:hover { background: var(--surface-hover); color: var(--text-body); }
.date-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.date-pick[aria-expanded="true"] { background: var(--surface-selected); color: var(--accent-text); }
.date-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 70; width: 272px; padding: 10px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-overlay);
}
.date-pop-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.date-pop-head strong { font-size: var(--fs-sm); color: var(--text-body); }
.date-nav { width: 32px; height: 32px; border: 0; background: none; border-radius: var(--radius); font-size: 20px; line-height: 1; cursor: pointer; color: var(--text-body); }
.date-nav:hover { background: var(--surface-hover); }
.date-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.date-dow { padding: 4px 0; text-align: center; font-size: var(--fs-2xs); font-weight: 700; color: var(--text-muted); }
.date-day {
  height: 32px; border: 0; background: none; border-radius: var(--radius); cursor: pointer;
  font: inherit; font-size: var(--fs-sm); color: var(--text-body); font-variant-numeric: tabular-nums;
}
.date-day:hover { background: var(--surface-hover); }
.date-day.is-today { box-shadow: inset 0 0 0 1px var(--accent); }
.date-day.is-chosen { background: var(--accent-solid); color: var(--text-on-accent); }
.date-day:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.date-pop-foot { display: flex; justify-content: space-between; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border-subtle); }

/* -- settings as steps (performance/views.ts settingsPage) ------------------------ */
.setup-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 8px; }
.setup-step {
  display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; min-width: 0;
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface);
  color: inherit; text-decoration: none;
}
a.setup-step:hover { border-color: var(--border-hover); text-decoration: none; }
.setup-step.is-active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); background: var(--surface-selected); }
.setup-step.is-blocked { opacity: .55; }
.setup-step-no {
  flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface-sunken); color: var(--text-secondary); font-size: var(--fs-xs); font-weight: 700;
}
.setup-step.is-done .setup-step-no { background: var(--ok-tint); color: var(--ok-text); }
.setup-step.is-next .setup-step-no { background: var(--accent-solid); color: var(--text-on-accent); }
.setup-step-text { display: grid; gap: 2px; min-width: 0; }
.setup-step-text strong { font-size: var(--fs-sm); color: var(--text-body); }
.setup-step-text small { font-size: var(--fs-2xs); color: var(--text-muted); line-height: 1.35; }
.setup-step-new { border-style: dashed; }
.setup-step-hint { margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
/*
 * A STEP'S CONTENT STARTS AT ONE HEIGHT ON EVERY STEP (2026-10-29): where the
 * longest hint (Harf notu ve prim, 1387px on one line, measured) wraps, every
 * step holds two lines, so the one-line steps do not start 20px higher. Where
 * it fits, none does: the period step needs those 20px not to scroll on a
 * 1920x1080 screen. A longer hint moves the 1400px.
 */
.setup-pane > .pane-head { container: setup-head / inline-size; }
@container setup-head (max-width: 1400px) {
  .setup-step-hint { min-height: 3em; min-height: 2lh; }
}
@media (max-width: 760px) { .setup-steps { grid-template-columns: 1fr 1fr; } }

/* -- the card screen: its next step in view, its lower half in tabs (views.ts cardPage) -- */
.context-aside.is-plain { padding: 0; background: none; border: 0; box-shadow: none; gap: var(--rhythm); }
/*
 * STACKED. Below 1700px the goal sheet takes the whole width (its 920px
 * floor, above), so the column drops: its box dissolves and its cards follow
 * the sheet - or, for a decision (`.is-first-on-top`), "Şimdi ne
 * yapmalısınız?" stands above it. Before, the step sat a thousand pixels down.
 */
@media (max-width: 1700px) {
  .card-split:has(.goal-grid) > .context-aside.is-plain { display: contents; }
  .card-split.is-first-on-top:has(.goal-grid) > .context-aside.is-plain > :first-child { order: -1; }
}
@media (max-width: 1100px) {
  .card-split > .context-aside.is-plain { display: contents; }
  .card-split.is-first-on-top > .context-aside.is-plain > :first-child { order: -1; }
}
/* In the narrow column the "why not yet" trio reads down, not across. */
@media (min-width: 1701px) {
  .context-aside.is-plain .blocked-step { grid-template-columns: minmax(0, 1fr); }
}

/* Tabs (components.ts tabSet): the card's lower half, the letter-grade screen. */
.tab-set { display: grid; gap: 12px; scroll-margin-top: 84px; min-width: 0; }
.tab-bar a[aria-current="true"] { background: var(--accent-solid); border-color: var(--accent-solid); color: var(--text-on-accent); }
.tab-panel { display: grid; gap: var(--rhythm); min-width: 0; scroll-margin-top: 84px; }
.tab-panel[hidden] { display: none; }
/* Without script the bar is a row of links down to the stacked panels. */
.tab-set:not(.is-tabbed) .tab-panel + .tab-panel { margin-top: 4px; }
@media print { .tab-panel[hidden] { display: grid !important; } }

/* "Sıradaki işiniz": the reader's next card, once this one no longer waits on them. */
.next-work {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0;
  padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface); font-size: var(--fs-sm); color: var(--text-secondary);
}
.next-work > svg { color: var(--text-icon); flex: none; }
.next-work > span { flex: 1 1 240px; min-width: 0; }
.next-work strong { color: var(--text-body); }

/* The card's letter, beside its step. */
.card-grade {
  display: inline-flex; align-items: baseline; gap: 6px; margin-left: 8px; padding: 2px 8px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
  color: var(--text-secondary); white-space: nowrap;
}
.card-grade strong { font-size: var(--fs-sm); color: var(--text-body); }

/* -- the pano: today's work first (views.ts panoPage) ------------------------------- */
.pano-overview { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--rhythm); align-items: start; }
.pano-overview > * { min-width: 0; }
.pano-overview .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.pano-overview .metric { padding: 12px 14px; }
.pano-overview .metric .value { margin-top: 6px; font-size: 21px; }
@media (max-width: 1100px) { .pano-overview { grid-template-columns: minmax(0, 1fr); } .pano-overview .metrics { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); } }
/* The board's filter rides under the top bar while its list scrolls. */
@media (min-width: 761px) {
  .board-filter-bar {
    position: sticky; top: 72px; z-index: 4;
    background: var(--surface); border-bottom: 1px solid var(--border-subtle);
  }
}

/* -- "Bu sayfada ne yapılır?" beside the title (components.ts pageHead `help`) --------- */
/* The wave clips itself (border-radius: inherit), so the head may let a pop-up out. */
.page-head:has(.page-help) { overflow: visible; }
/* The head is its own layer (isolation): while its pop-up is open it rises over what follows. */
.page-head:has(.page-help[open]) { z-index: 30; }
.page-help { position: relative; }
.page-help > summary { list-style: none; cursor: pointer; }
.page-help > summary::-webkit-details-marker { display: none; }
.page-help[open] > summary { color: var(--accent-text); }
.page-help-panel {
  position: absolute; z-index: 40; top: calc(100% + 8px); left: 0;
  width: min(560px, calc(100vw - 48px)); padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-overlay);
}
.page-help-panel .help-list { margin: 0; }
@media (max-width: 760px) {
  .page-help { position: static; }
  .page-help-panel { left: 16px; right: 16px; width: auto; top: auto; margin-top: 8px; }
}
@media print { .page-help { display: none !important; } }

/*
 * A TIGHTER HEAD (2026-10-28). Every screen opened on a 200px hero before the
 * first thing to do; the title, its line and its buttons fit in less, and the
 * page's help is a pop-up beside the title now instead of a row under it.
 */
.page-head { padding: 16px 24px; gap: 16px; }
.page-head h1 { font-size: 24px; }
.page-head .eyebrow { margin-bottom: 4px; }
.page-head p { margin-top: 4px; }
.page-head-compact { padding: 2px 0 0; }
@media (max-width: 760px) { .page-head { padding: 14px 16px; } .page-head h1 { font-size: 22px; } }

/* A long table scrolls inside its panel, its head standing (the card's ledger,
   Olay Defteri, the grade tables) - the same as the users' account lists. */
.table-pane .scroll-x { max-height: min(620px, 65vh); overflow: auto; overscroll-behavior: contain; }
@media print { .table-pane .scroll-x { max-height: none; overflow: visible; } }

/* ==========================================================================
   THE SCREEN IS THE PAGE (2026-10-28)
   ========================================================================== */
/*
 * "SITE FORMATI KAYDIRMALI DEĞİL, SÜREÇTE HEP TAM EKRANA SIĞMALI." Measured
 * before at 1440x900: the pano was 2900px, a card 2520px, the reader scrolled
 * three screens to do one step. On a screen wide and tall enough for it the
 * window no longer scrolls at all:
 *
 *   - the shell is the screen's height, the rail and the top bar stand still;
 *   - the page's own head sits IN the top bar (layout.ts `head`), not as a
 *     140px panel under a bar that already said its name;
 *   - a page laid out in panes (`main.is-fit`, components.ts `pane` and
 *     `workspace`) scrolls only inside them - a list, a table, a long text;
 *   - a page not laid out that way yet scrolls inside <main> (`is-flow`), so
 *     the bar and the head stay in view there too.
 *
 * Below 1101px wide (the rail is a strip across the top) or 600px tall there
 * is no screen to fit into: the page scrolls as a document, as it always did,
 * with the head as its first panel.
 */
.page-bar { padding: 24px 24px 0; max-width: var(--shell-max); }
.page-bar + .main { padding-top: var(--rhythm); }

@media (min-width: 1101px) and (min-height: 600px) {
  html { scrollbar-gutter: auto; }
  .shell { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; }
  .main-col {
    height: 100vh; height: 100dvh; min-height: 0;
    display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto minmax(0, 1fr);
  }
  .topbar { grid-row: 1; grid-column: 1 / -1; position: relative; }
  .main-col:has(> .page-bar) > .topbar { grid-column: 2; padding-left: 16px; }
  .main-col:has(> .page-bar) .topbar-title { display: none; }

  /* The head, one strip with the bar: the same height, ground and rule. */
  .page-bar {
    grid-row: 1; grid-column: 1; min-width: 0; max-width: none;
    height: 72px; padding: 0 0 0 28px;
    display: flex; align-items: center;
    background: var(--surface); border-bottom: 1px solid var(--border);
  }
  .page-bar .page-head {
    width: 100%; min-width: 0; flex-wrap: nowrap; gap: 16px;
    padding: 0 0 0 19px; overflow: visible;
    background: none; box-shadow: none; border-radius: 0;
  }
  /* The bar's red mark, beside the title as the top bar drew it. */
  .page-bar .page-head::before {
    content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
    width: 4px; height: 36px; background: var(--accent);
  }
  .page-bar .hero-wave { display: none; }
  .page-bar .page-head .grow { min-width: 0; }
  .page-bar .page-head h1 { font-size: 19px; line-height: 1.25; letter-spacing: -0.02em; white-space: nowrap; }
  .page-bar .page-head .eyebrow {
    margin-bottom: 1px; font-size: 12px; letter-spacing: .12em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* As wide as the bar leaves it (it was cut at 72 characters beside 800px of nothing). */
  .page-bar .page-head p {
    margin-top: 1px; font-size: 13.5px; line-height: 1.4; max-width: min(120ch, 100%);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .page-bar .page-head-title { flex-wrap: nowrap; gap: 10px; }
  /*
   * ONE HEAD ON EVERY SCREEN (2026-10-29): the name and its (?) (i), nothing
   * over or under it. A taller monitor added a spaced-out red line above the
   * name and the description's first sentence under it - "2. adım — günlük
   * iş." alone read as a fragment - so the same page looked different from
   * desk to desk. The description is the (i) help's first line and its hover.
   */
  .page-bar, .main-col:has(> .page-bar) > .topbar { height: 60px; }
  .page-bar .page-head .eyebrow, .page-bar .page-head .grow > p { display: none; }
  .page-bar .page-head::before { height: 30px; }
  /* The buttons keep their width; the description gives way to them, never the other way. */
  .page-bar .page-head-actions { flex: none; flex-wrap: nowrap; }
  .page-bar .page-head-actions > * { flex: none; }
  .page-bar .page-head-actions .btn { height: 36px; padding-inline: 12px; }
  /* "Nasıl kullanılır?" and "Bu sayfada ne yapılır?" as their two marks: the
     words stay for a screen reader and on hover (title), the strip keeps its
     room for the title and the page's buttons. */
  .page-bar .page-guide > span:not(.page-guide-mark) {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }

  /* THE RAIL FITS TOO: the same 278px, rows a little closer, so an
     administrator's eighteen links stand without a scrollbar at 900px. */
  .sidebar-brand { padding-top: 18px; }
  .sidebar-brand span { margin-top: 14px; padding-block: 9px; }
  .sidebar-section { padding: 12px 22px 5px; }
  .sidebar-link { padding-block: 6px; }
  .sidebar-version { padding-block: 10px; }

  .main { grid-row: 2; grid-column: 1 / -1; min-height: 0; max-width: none; }
  .page-bar + .main { padding-top: 20px; }
  /* Not laid out in panes yet: the page scrolls inside <main>, never the window. */
  .main.is-flow { overflow-y: auto; overscroll-behavior: contain; }
  /* The same edges as a page in panes: one page's boxes ended 60px short of the next one's. */
  .main.is-flow, .page-bar + .main.is-flow { padding: 16px 20px; }
  .main.is-flow > * { max-width: none; }
  /* Laid out in panes: <main> is the screen's remainder, and only the panes scroll. */
  .main.is-fit {
    overflow: hidden; display: flex; flex-direction: column; gap: 12px;
    padding: 16px 20px 16px;
  }
  .main.is-fit > * + * { margin-top: 0; }
  .page-bar + .main.is-fit { padding-top: 16px; }

  /* An anchor lands at the top of the box that scrolls, not 88px under a bar. */
  [id] { scroll-margin-top: 12px; }
  /* What stood still under the 72px bar while the window scrolled stands at its box's top. */
  .contents-rail, .manual-side, .guide-side, .request-side, .context-aside.is-sticky { top: 0; }
  .contents-rail, .manual-side { max-height: calc(100dvh - 140px); }
  .context-aside.is-sticky { max-height: calc(100dvh - 140px); }
  .ctr-toolbar, .card-sticky-head > .card-head, .board-filter-bar { top: -24px; }
  .diff-cols-head { top: 36px; }
}

/* -- the account menu (layout.ts userMenu) ---------------------------------- */
.user-menu { position: relative; }
.user-menu > summary { list-style: none; cursor: pointer; }
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu-button {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 8px 4px 4px; border-radius: var(--radius);
  color: var(--text-secondary);
}
.user-menu-button:hover, .user-menu[open] > .user-menu-button { background: var(--surface-hover); }
.user-menu-button .topbar-who strong { color: var(--text-body); }
.user-menu-panel {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  width: 260px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-overlay);
}
.user-menu-who {
  display: flex; flex-direction: column; gap: 2px; margin: 0 0 6px; padding: 8px 10px 10px;
  border-bottom: 1px solid var(--border); line-height: 1.3;
}
.user-menu-who em { font-style: normal; font-size: var(--fs-2xs); color: var(--text-muted); overflow-wrap: anywhere; }
.user-menu-link {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: var(--radius);
  background: none; font: inherit; font-size: var(--fs-sm); color: inherit; text-align: left; cursor: pointer;
}
.user-menu-link:hover { background: var(--surface-hover); }
.user-menu-out { color: var(--accent-text); }
/* The name beside the avatar only where the bar has room for it; the menu always says it. */
@media (max-width: 1500px) { .user-menu-button .topbar-who { display: none; } }
@media print { .page-bar .page-help, .user-menu { display: none !important; } }

/* ==========================================================================
   Panes and the work desk (components.ts pane/workspace, views.ts desk*)
   ========================================================================== */
/*
 * A PANE IS A PANEL WITH A HEAD THAT STAYS, A BODY THAT SCROLLS AND A FOOT
 * THAT STAYS. On a wide screen panes share the screen and only their bodies
 * scroll; below it they are panels in a page that scrolls, the foot sticking
 * to the bottom edge - `overflow: clip`, not hidden, because a clipping box
 * that is a scroll container would hold the sticky foot inside itself.
 */
.pane {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card); overflow: clip;
}
/*
 * THE HEAD AND THE FOOT ON A GREY BAND, THE CONTENT WHITE (2026-10-29): with
 * all three white, a pane's search, filters and tabs ran into the list under
 * them ("bütün panel beyaz diye header kısmı ile içerik okunamıyor"). Not the
 * warm band 15.09 turned down, and not grey either: a grey band read as the
 * page showing through. --surface-band-head, a cool tint every text colour
 * is measured against (scripts/check.ts).
 */
.pane-head {
  flex: none; display: flex; flex-direction: column; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid var(--border-subtle);
  background: var(--surface-band-head);
}
.pane-body { min-width: 0; }
.pane-foot {
  flex: none; border-top: 1px solid var(--border);
  background: var(--surface-band-head); position: sticky; bottom: 0; z-index: 6;
}
/* A neutral badge is filled with the band's own grey: on a band it is white. */
:is(.pane-head, .pane-foot, .card-head) .badge-neutral { background: var(--surface); }
/* A tab pane's foot slot is drawn even empty, for a step that appears in place (components.ts tabPane). */
.pane-foot:has(> .swap-slot:empty) { display: none; }
.ws { display: flex; flex-direction: column; gap: var(--rhythm); }

@media (min-width: 1101px) and (min-height: 600px) {
  /*
   * EVERY BOX ON A FIT SCREEN ENDS AT THE PAGE'S BOTTOM MARGIN (2026-10-29,
   * the user's rule). The same margin the page keeps at its top and sides is
   * kept at its foot, and the panes reach it - always, whatever they hold.
   *
   * Two rounds came before. First each pane ended where its content did
   * ("sayfa en üste kayık" had been about a short form in a screen-tall box),
   * then side-by-side panes took the taller one's height. Both left the frame
   * moving whenever its content changed: the work desk's card ended at 845px
   * for one person (scoring) and 768px for the next (1. onay), so "Kaydet ve
   * onaya gönder" and "1. onayı ver" stood 77px apart and the reader could not
   * tell the step had moved on. A frame that never moves, and its action bar
   * at its foot, is what reads as going forward. A short panel keeps some
   * white under its content; a long one scrolls inside itself.
   */
  .ws {
    flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 12px;
    grid-template-rows: minmax(0, 1fr); align-items: stretch;
  }
  .ws > * { max-height: 100%; }
  .ws.is-single { grid-template-columns: minmax(0, 1fr); }
  .pane { min-height: 0; }
  .main.is-fit > .pane { flex: 1 1 auto; }
  .pane-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
  .pane-foot { position: static; }
}

/* -- the list -------------------------------------------------------------- */
.desk-modes { display: flex; }
.desk-modes > button { flex: 1; justify-content: center; gap: 6px; }
.desk-count { font-weight: 700; opacity: .8; }
.desk-filter { display: grid; gap: 8px; }
.desk-filter-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.desk-filter .field { margin: 0; }
.desk-filter .control { height: var(--control-h-sm); font-size: var(--fs-sm); }
/* The switch and the filter are the script's; without it both lists stand titled. */
html:not(.js) .desk-modes, html:not(.js) .desk-filter { display: none; }
.js .desk-panel-title { display: none; }
.js .desk-panel[data-desk-later] { display: none; }
.desk-panel-title {
  margin: 0; padding: 12px 16px 0;
  font-size: var(--fs-xs); color: var(--text-muted);
}
/*
 * A GROUP'S NAME IS A BAND (2026-10-29): "Hedefleri girin", "1. onayı ver"
 * stood in grey letters on the same white as the people under them and the
 * eye did not find where one step's people ended. Now a band between two
 * lines, in the body's own ink - --surface-band-group, a step stronger
 * than the heads: a grey one looked like the page.
 */
.desk-group-head {
  display: flex; justify-content: space-between; gap: 8px; margin: 0;
  padding: 7px 16px;
  font-size: var(--fs-xs); font-weight: 700;
  color: var(--text-body);
  background: var(--surface-band-group);
  border-block: 1px solid var(--border);
}
.desk-group:first-child > .desk-group-head { border-top: 0; }
.desk-row {
  display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; align-items: center; gap: 10px;
  padding: 8px 16px 8px 13px; border-left: 3px solid transparent;
  color: inherit; text-decoration: none;
}
.desk-row:hover { background: var(--surface-hover); }
.desk-row:focus-visible { outline-offset: -2px; }
.desk-row.is-current {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-left-color: var(--accent);
}
.desk-row[hidden], .desk-group[hidden] { display: none; }
.desk-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); }
.desk-row.is-wait .desk-dot { background: var(--accent); }
.desk-row.is-done .desk-dot { background: var(--ok); }
.desk-row.is-idle .desk-dot { background: var(--info); opacity: .55; }
.desk-row.is-off .desk-dot { background: transparent; border: 1px solid var(--text-muted); }
.desk-row.is-off .desk-name { text-decoration: line-through; color: var(--text-muted); }
.desk-text { display: flex; flex-direction: column; min-width: 0; }
.desk-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A long department goes on a second line rather than being cut ("HAZİNE YÖNETİMİ ve MÜŞTERİ DEN…"). */
.desk-sub { overflow-wrap: anywhere; }
.desk-name { font-size: var(--fs-sm); font-weight: 600; }
.desk-sub { font-size: var(--fs-2xs); color: var(--text-muted); }
.desk-due { font-size: var(--fs-2xs); color: var(--text-muted); }
.desk-score { font-size: var(--fs-xs); font-weight: 600; }
.desk-empty { margin: 0; padding: 16px; color: var(--text-muted); font-size: var(--fs-sm); }
.desk-list .empty { margin: 12px; }
.desk-list .pane-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 16px;
  position: static; /* only a step's buttons stick to the bottom of a phone's screen */
}
.desk-foot-note { margin: 0; font-size: var(--fs-2xs); color: var(--text-muted); }

/* -- the board's summary (no card chosen) ----------------------------------- */
.desk-title { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }
.desk-summary-head { flex-direction: row; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.desk-summary-head .period-switch { margin: 0; padding: 0; border: 0; box-shadow: none; background: none; }
.desk-summary .pane-body { padding: 16px; display: flex; flex-direction: column; gap: 14px; }
.desk-summary .pane-body > * + * { margin-top: 0; }
.desk-next {
  display: flex; align-items: center; gap: 16px; padding: 14px 18px;
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
  border-left: 4px solid var(--accent); border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--accent) 5%, var(--surface));
  color: inherit; text-decoration: none;
}
a.desk-next:hover { background: color-mix(in srgb, var(--accent) 9%, var(--surface)); }
.desk-next .eyebrow { margin: 0; }
.desk-next-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.desk-next-name { font-size: 18px; }
.desk-next-hint { font-size: var(--fs-sm); color: var(--text-secondary); }
.desk-next.is-clear {
  border-color: color-mix(in srgb, var(--ok) 30%, var(--border)); border-left-color: var(--ok);
  background: color-mix(in srgb, var(--ok) 6%, var(--surface)); color: var(--text-body);
}
.desk-next.is-clear > svg { color: var(--ok-text); flex: none; }
.desk-progress {
  display: flex; flex-direction: column; gap: 10px; padding: 14px 16px;
  border: 1px solid var(--border-subtle); border-radius: var(--radius-lg);
}
.desk-progress-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.desk-progress h3 { margin: 0; font-size: var(--fs-base); }
.desk-summary .footnote { margin: 0; }

/* -- the card, in steps ------------------------------------------------------ */
/* The card is its own measure: what fits in its head and foot depends on the
   card's width, not the window's (the list beside it takes its share). */
.desk-card { container: deskcard / inline-size; }
.desk-card .pane-head { padding: 12px 16px 0; gap: 10px; }
.desk-card-title { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 12px; }
.desk-card-meta { font-size: var(--fs-sm); color: var(--text-muted); }
.desk-previous {
  margin-left: auto; display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-sm); color: var(--accent-text);
}
.desk-back { display: none; align-items: center; gap: 2px; font-size: var(--fs-sm); color: var(--accent-text); }
/* The step bar and the chain, one line each, inside the card's head. */
.desk-card .step-tracker {
  padding: 0; border: 0; box-shadow: none; background: none;
  flex-wrap: nowrap; overflow: hidden; gap: 4px 12px;
}
.desk-card .step-tracker-item { gap: 5px; white-space: nowrap; font-size: 12.5px; }
.desk-card .step-tracker-dot { width: 18px; height: 18px; }
.desk-card .chain-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.desk-card .chain-strip .person-chip { padding: 6px 10px; box-shadow: none; }
.desk-card .chain-strip .person-chip .label { margin-bottom: 0; }
/*
 * EVERY CHAIN CHIP THE SAME HEIGHT, ON EVERY CARD (2026-10-29). A "Sırada"
 * or "Siz" mark made its line 2px taller, and an empty slot's "tanımsız"
 * took a third line: the chain row was 51, 53 or 71px from one person to the
 * next and everything under it - the tabs, the sheet - moved with it. Two
 * lines of fixed height; the note stands beside the "—".
 */
.desk-card .chain-strip .person-chip { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 6px; align-content: center; }
.desk-card .chain-strip .person-chip > .label { grid-column: 1 / -1; display: flex; align-items: center; gap: 4px; height: 20px; }
.desk-card .chain-strip .person-chip > strong { display: flex; align-items: center; gap: 4px; height: 22px; min-width: 0; }
.desk-card .chain-strip .person-chip-note { margin: 0; align-self: center; }
.desk-card .chain-strip .person-chip-sicil { align-self: center; }
.desk-card-title { min-height: 30px; align-items: center; }
/* The card's tabs read as tabs: a line under the current one, not a row of buttons. */
.desk-tabs {
  display: flex; flex-wrap: nowrap; overflow-x: auto; gap: 2px;
  margin: 0 -16px; padding: 0 12px; border-top: 1px solid var(--border-subtle);
}
.desk-tabs.segmented a, .desk-tabs.segmented a + a {
  height: 40px; padding: 0 12px; border: 0; border-bottom: 2px solid transparent; border-radius: 0;
  background: none; color: var(--text-secondary); white-space: nowrap;
}
.desk-tabs.segmented a:hover:not([aria-current]) { background: none; color: var(--text-body); }
.desk-tabs.segmented a[aria-current="true"] {
  background: none; border-bottom-color: var(--accent); color: var(--text-body);
}
html:not(.js) .desk-tabs { display: none; }
.desk-card .pane-body { padding: 16px; }
/* Each tab measures itself: the goal sheet folds to the width IT has, beside the evidence or not. */
.desk-card .tab-panel { container-type: inline-size; }
.desk-card .tab-panel > * + * { margin-top: var(--rhythm); }
.desk-card .tab-panel > .card { box-shadow: none; }
/* The evidence in two columns where the panel has the room; the potential form takes the row. */
.desk-context { display: grid; gap: 14px 24px; }
@container (min-width: 700px) {
  .desk-context { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .desk-context .labelled-group:has(form) { grid-column: 1 / -1; }
}
.desk-context .panel-empty { padding: 6px 0; margin: 0; }
.desk-card .legend-strip { margin-bottom: 4px; font-size: var(--fs-2xs); }
.desk-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.desk-sheet-head h3 { margin: 0; font-size: var(--fs-base); }
.desk-sheet .card-foot { padding: 10px 0 0; border: 0; background: none; }
.desk-sheet .goal-grid { border: 1px solid var(--border-subtle); }
.goal-entry-form .goal-pick { width: auto; }

/* The goal sheet in a panel narrower than its 920px: the type and the
   description go under the title, and a sheet being typed drops the two
   score columns it can only show as a dash. */
.desk-card .goal-grid { min-width: 0; }
.goal-sub { display: none; }
.goal-entry-form .goal-grid .goal-score, .goal-entry-form .goal-grid .goal-points { display: none; }
@container (max-width: 960px) {
  /* Narrowed to nothing rather than removed: the totals row spans four
     columns, and with two of them gone it ran two short and the sheet kept a
     blank strip down its right side. */
  .goal-grid:not(:has(.goal-entry-choice)) .goal-type,
  .goal-grid:not(:has(.goal-entry-choice)) .goal-detail {
    width: 0; min-width: 0; padding: 0; border: 0; overflow: hidden; visibility: hidden; font-size: 0;
  }
  .goal-grid:not(:has(.goal-entry-choice)) .goal-detail > * { display: none; }
  .goal-grid:not(:has(.goal-entry-choice)) .goal-sub {
    display: block; margin-top: 2px; font-size: var(--fs-2xs); color: var(--text-muted); font-weight: 400;
  }
  .goal-grid:not(:has(.goal-entry-choice)) .goal-pick { width: auto; }
  .goal-entry-form .goal-type { width: 170px; min-width: 170px; }
}

/* -- the card's foot: this step's buttons ------------------------------------ */
/*
 * ONE HEIGHT FOR EVERY STEP'S ACTION BAR (2026-10-29): a bar of buttons, one
 * with a reason box and one with only a sentence (a completed card) were
 * 63, 65 and 41px tall, so the line above them moved from person to person.
 * Every bar is now at least a button's height and its padding.
 */
.action-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; padding: 10px 16px; margin: 0; min-height: calc(var(--control-h) + 20px); }
.action-bar-text { flex: 1 1 260px; min-width: 0; }
.action-bar-say { margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.action-bar-why { margin: 2px 0 0; font-size: var(--fs-2xs); color: var(--text-muted); }
.action-bar-warn { display: flex; align-items: center; gap: 6px; margin: 2px 0 0; font-size: var(--fs-2xs); color: var(--warn-text); }
.action-bar-note { flex: 1 1 200px; max-width: 340px; min-width: 160px; }
.action-bar-note .control { width: 100%; min-height: 36px; height: 36px; padding: 7px 10px; resize: vertical; }
.action-bar-buttons { display: flex; align-items: center; gap: 8px; flex: none; }
.action-bar.is-waiting { background: var(--surface-sunken); }
/* A narrow card: the sentence takes its own line over the box and the buttons,
   and the step bar keeps the names of the steps still to come and the current one. */
@container deskcard (max-width: 860px) {
  .desk-card .step-tracker-item.is-done .step-tracker-label { display: none; }
  /* The sentence beside the buttons, two lines at most; a reason box takes its own row. */
  .action-bar-text { flex: 1 1 200px; }
  .action-bar-say { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .action-bar:has(.action-bar-note) .action-bar-text { flex-basis: 100%; }
  .action-bar-note { max-width: none; }
  /*
   * ONE SHAPE FOR EVERY STEP'S BAR ON A NARROW CARD (2026-10-29). Wrapping
   * made it one row for a step with buttons, two for a step with a reason
   * box, and the sentence one line or two: the bar was 56, 85 or 91px tall
   * from one person to the next. Now always two rows - the sentence (room
   * for two lines), then the reason box and the buttons - and the second
   * row is held even on a card with nothing to press.
   */
  .desk-card .action-bar {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto var(--bar-row, var(--control-h)); align-items: center;
  }
  .desk-card .action-bar-text { grid-column: 1 / -1; }
  .desk-card .action-bar-say { min-height: 2lh; }
  .desk-card .action-bar-note { grid-row: 2; grid-column: 1; }
  .desk-card .action-bar-buttons { grid-row: 2; grid-column: 2; }
}
@container deskcard (max-width: 560px) {
  .action-bar-text { flex-basis: 100%; }
}
@media (max-width: 760px) {
  .action-bar { padding: 10px 12px; }
  .action-bar-note { flex-basis: 100%; }
  .action-bar-buttons { flex: 1 1 100%; flex-wrap: wrap; }
  .action-bar-buttons > .btn { flex: 1 1 140px; justify-content: center; }
}
/*
 * BAĞLAM IS A TAB ON EVERY SCREEN (2026-10-28). On a 1920px screen it stood as
 * a column beside "Bu adım" and its tab left the bar - so pressing "Akran
 * görüşü" made "Bağlam" appear and every tab after it move ("akran görüşüne
 * tıklıyorum bağlam diye bir şey geliyor"), and the scores' legend stood
 * over an empty band the column's height. One bar, the same tabs, always.
 */

/* Below the fit width: the board is the list then the summary, a card is the card alone. */
@media (max-width: 1100px), (max-height: 599px) {
  .ws.has-card > .desk-list { display: none; }
  .desk-back { display: inline-flex; }
  .desk-card .chain-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media print {
  .pane { overflow: visible; box-shadow: none; }
  .pane-foot, .desk-list, .desk-tabs { display: none !important; }
  .desk-card .tab-panel[hidden] { display: block !important; }
}

/* -- the setup as a frame: the steps above, one step's work, the way on below ----- */
.setup-pane .pane-head { gap: 8px; }
.setup-pane .setup-steps { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.setup-pane .setup-step { padding: 8px 10px; }
.setup-pane .setup-step-no { width: 24px; height: 24px; }
.setup-pane .setup-step-text small { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.setup-pane .pane-body { padding: 16px; }
.setup-pane .setup-step-body > .card { box-shadow: none; }
.step-nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 16px; }
.step-nav .btn { max-width: 48%; }
/* The step's save and the way on stand together at the right; the way back alone at the left. */
.step-nav-end { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-left: auto; min-width: 0; }
.step-nav-end .btn { max-width: none; }
.step-nav .btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 760px) {
  .setup-pane .setup-steps { grid-template-columns: 1fr 1fr; }
  /* A long step's name wraps on its own full line; it ran off the phone's edge. */
  .step-nav { flex-wrap: wrap; }
  .step-nav .btn { max-width: 100%; flex: 1 1 100%; min-width: 0; height: auto; min-height: var(--control-h); }
  .step-nav .btn span { white-space: normal; }
  .step-nav-end { flex: 1 1 100%; flex-wrap: wrap; margin-left: 0; }
}

/* -- a pane of tabs (components.ts tabPane): Harf Notu, the karne, the org chart -- */
.tab-pane-frame .pane-head { padding: 12px 16px 0; }
.tab-pane-frame .pane-body { padding: 16px; }
.tab-pane-frame .tab-panel { container-type: inline-size; }
.tab-pane-frame .tab-panel > * + * { margin-top: var(--rhythm); }
.tab-pane-frame .tab-panel > .card { box-shadow: none; }
.pane-summary { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px 16px; }
.pane-summary .period-switch { margin: 0; padding: 0; border: 0; box-shadow: none; background: none; }
.pane-counts { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.pane-counts strong { margin-left: 4px; color: var(--text-body); }

/* -- a pane that is one long table (the ledger, the people lists) ------------------ */
/* The table scrolls, not the pane: its head row stands at the top while it does. */
.pane-note { padding: 10px 16px; display: grid; gap: 4px; }
.pane-note .card-note { margin: 0; }
.pane.is-table .table-pane .scroll-x, .pane.is-table > .pane-body > .scroll-x { border: 0; }
@media (min-width: 1101px) and (min-height: 600px) {
  .pane.is-table > .pane-body { overflow: hidden; display: flex; flex-direction: column; }
  .pane.is-table > .pane-body > .table-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .pane.is-table > .pane-body > .table-pane > .scroll-x,
  .pane.is-table > .pane-body > .scroll-x { flex: 1; min-height: 0; max-height: none; overflow: auto; }
}
.pane-head .perf-team-filters { margin: 0; }

/* -- support on one screen: the list and the conversation (or the new form) fill it -- */
@media (min-width: 1101px) and (min-height: 600px) {
  /*
   * The list and the conversation (or the new-request form) reach the page's
   * bottom margin together, as every fit screen's boxes do (2026-10-29); the
   * messages scroll inside.
   */
  .main.is-fit > .sup-layout { flex: 1; min-height: 0; --tk-h: 100%; grid-template-rows: minmax(0, 1fr); align-items: stretch; }
  .main.is-fit > .sup-layout > .tk:not(.tk-new) { height: 100%; }
  .main.is-fit > .sup-layout > .sup-side, .main.is-fit > .sup-layout > .tk-new { height: auto; max-height: 100%; }
}
.tk-new { overflow-y: auto; overscroll-behavior: contain; padding: 0; }
.tk-new > .sup-new > summary { display: none; }
.tk-new .sup-new > .card, .tk-new .card { border: 0; box-shadow: none; }
@media (max-width: 1100px) {
  .sup-layout.is-mine .sup-side { display: flex; height: auto; max-height: 360px; }
  .sup-layout.is-mine .tk-new { height: auto; }
}

/* -- a card that is the whole page (the release notes, the appearance screen) ------ */
@media (min-width: 1101px) and (min-height: 600px) {
  .main.is-fit > .card.is-fill, .main.is-fit > form > .card.is-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .main.is-fit > form:has(> .card.is-fill) { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .card.is-fill > .card-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
  /* The guide: its contents and its reading, each scrolling in its own column. */
  .main.is-fit > .manual-book { flex: 1; min-height: 0; align-items: stretch; }
  .main.is-fit > .manual-book > .manual-side { position: static; max-height: none; min-height: 0; }
  .main.is-fit > .manual-book > .manual-content { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 4px; }
}

/* The incoming queue fills its pane; Sistem Sağlığı's four groups stand two by two. */
@media (min-width: 1101px) and (min-height: 600px) {
  .sup-queue-pane > .pane-body { display: flex; flex-direction: column; }
  .sup-queue-pane .sup-scroll-fixed { flex: 1; min-height: 0; max-height: none; height: auto; }
}
.health-groups { display: grid; gap: var(--rhythm); }
/* Two groups side by side: one top edge, one height (the second stood 16px lower on a margin of its own). */
.health-groups > * { margin: 0 !important; }
@media (min-width: 1101px) { .health-groups { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; } }


/*
 * NOTHING ESCAPES THE SCREEN. An absolutely placed thing with no placed
 * ancestor (a screen-reader-only label, a hidden radio) sits at its spot in
 * the page and, inside a long scrolled form, stretched the window by a
 * hundred pixels: Taleplerim and Görünüm scrolled as a whole at 1366x650.
 * The shell and the boxes that scroll are their containing blocks now.
 */
@media (min-width: 1101px) and (min-height: 600px) {
  .shell, .main, .pane-body, .card.is-fill > .card-body, .tk-new, .manual-content { position: relative; }
}

/* ==========================================================================
   A STEP FITS ITS SCREEN (2026-10-28, second pass)
   ========================================================================== */
/*
 * "BÜTÜN ARAYÜZÜ CİDDEN SIĞDIR, NİZAMİ ŞEKLE ÇEK, HİZALA." Measured at
 * 1366x650 - a laptop's browser window - a card's goal sheet ran 276px under
 * its own edge, a settings step up to 600. The rule now: a step's own work
 * (a form, a sheet, a summary) fits; only a list that grows with the company
 * scrolls, and says so (app.js moreBelow).
 */

/* -- the card's head, everywhere: one line per fact -------------------------- */
/* The chain: role over name, the SİZ/SIRADA marks on the name's line; the
   sicil is in the card's own line above, not four times. */
.desk-card .chain-strip .person-chip { padding: 5px 10px; min-width: 0; }
.desk-card .chain-strip .person-chip strong { white-space: nowrap; }
.desk-card .chain-strip .person-chip-sicil { display: none; }
.desk-card .chain-strip .person-chip > * { vertical-align: middle; }
/* The 1-5 meanings in one quiet row over the scores. */
.desk-card .legend-strip-cols { gap: 2px 12px; }
.desk-card .legend-strip-cols li { gap: 5px; font-size: var(--fs-2xs); line-height: 1.3; }
.desk-card .legend-strip { margin-bottom: 6px; }
/* The sheet's rows a size down: a control 34px high in a 44px row. */
.desk-card .goal-grid tbody td, .karne-pane .goal-grid tbody td { padding-top: 5px; padding-bottom: 5px; }
.desk-card .goal-grid thead th, .karne-pane .goal-grid thead th { padding-top: 8px; padding-bottom: 8px; }
.desk-card .goal-grid tfoot td, .karne-pane .goal-grid tfoot td { padding-top: 8px; padding-bottom: 8px; }
.desk-sheet .card-foot { padding-top: 6px; }

/* -- a short screen: the frame gives its height to the work ------------------- */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  /* Both halves of the bar, with the selectors that set their 60px (they outrank a bare .topbar). */
  .topbar, .page-bar, .main-col:has(> .page-bar) > .topbar, .main-col:not(:has(> .page-bar)) > .topbar { height: 56px; }
  .topbar-title::before, .page-bar .page-head::before { height: 28px; }
  .page-bar .page-head h1 { font-size: 17px; }
  .page-bar .page-head .eyebrow { font-size: 12px; margin-bottom: 0; }
  /* The page's one-line description is its (i) help's first line and its hover. */
  .page-bar .page-head .grow > p { display: none; }
  .page-bar .page-head-actions .btn, .topbar .topbar-count { height: 34px; }
  .main.is-fit, .page-bar + .main.is-fit { padding: 10px 14px; gap: 10px; }
  .ws { gap: 10px; }
  .pane-head { padding: 8px 12px; gap: 8px; }
  /* The setup hint's held second line (a narrow pane) costs a 1366x768 step its last 2px: taken here. */
  .setup-pane .pane-head { gap: 6px; }
  .desk-card .pane-head, .tab-pane-frame .pane-head { padding: 8px 12px 0; gap: 6px; }
  .desk-card .pane-body, .tab-pane-frame .pane-body, .setup-pane .pane-body, .desk-summary .pane-body { padding: 10px 12px; }
  .desk-tabs { margin: 0 -12px; padding: 0 8px; }
  .desk-tabs.segmented a, .desk-tabs.segmented a + a { height: 34px; }
  .desk-title { font-size: 16px; }
  .desk-card .step-tracker-dot { width: 16px; height: 16px; }
  .action-bar, .step-nav, .desk-list .pane-foot { padding: 7px 12px; }
  .action-bar .btn, .step-nav .btn { height: 36px; }
  .action-bar { min-height: 50px; }
  .desk-card { --bar-row: 36px; }
  .action-bar-note .control { height: 36px; min-height: 36px; padding-block: 6px; }
  .desk-row { padding-top: 6px; padding-bottom: 6px; }
  .desk-group-head { padding-top: 8px; }
  .desk-filter .control { height: 32px; }
  .desk-summary .pane-body { gap: 10px; }
  .desk-next { padding: 10px 14px; }
  .desk-next-name { font-size: 16px; }
  .setup-pane .setup-step { padding: 6px 8px; }
  .setup-pane .setup-step-text small { display: none; }
  .table thead th { padding-top: 7px; padding-bottom: 7px; }
}

/* -- the board's summary: each fact one row, aligned to one grid --------------- */
/* The four phases in one row, the four counts in one row under them: two
   tidy rows on the same four columns, not a 2x2 of phases beside a 2x2 of tiles. */
.desk-summary .pano-overview { grid-template-columns: minmax(0, 1fr); gap: 10px; }
.desk-summary .phase-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.desk-summary .phase-strip li { padding: 10px 12px 8px; }
.desk-summary .phase-strip li.is-current { padding-top: 8px; }
.desk-summary .pano-overview .metrics { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.desk-summary .pano-overview .metric { padding: 8px 12px; box-shadow: none; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.desk-summary .pano-overview .metric .value { margin-top: 0; font-size: 20px; }
.desk-summary .desk-progress { padding: 10px 14px; gap: 8px; }
.desk-summary .labelled-group { margin: 0; }
@container (max-width: 640px) {
  .desk-summary .phase-strip, .desk-summary .pano-overview .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  /* On a short screen the summary keeps its facts and drops its repeats. */
  .desk-summary .phase-hint, .desk-summary .footnote { display: none; }
  .desk-summary .desk-next-hint { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .desk-summary .desk-progress { gap: 6px; }
}

/* -- a setup step's panels side by side, on one screen ------------------------------- */
@media (min-width: 1101px) and (min-height: 600px) {
  /* Panels side by side are one height: a row of boxes ending at different heights read as unfinished. */
  .setup-step-body { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 12px; align-items: stretch; }
  .setup-step-body > * { margin: 0 !important; min-width: 0; }
  /* One panel: the step bar above already says its name. */
  .setup-step-body > .card:only-child > .card-head { display: none; }
  .setup-pane .card-body { padding: 14px 16px; }
  .setup-pane .card-head { padding: 12px 16px; }
}


.setup-note {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin: 0; padding: 10px 14px;
  border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); background: var(--surface-sunken);
  font-size: var(--fs-sm); color: var(--text-secondary);
}
.setup-note > svg { flex: none; color: var(--text-muted); }
.setup-note > span { flex: 1; min-width: 200px; }
@media (min-width: 1101px) and (min-height: 600px) {
  .setup-step-body > .setup-note { grid-column: 1 / -1; }
  /*
   * THE REFERENCE STEP (2026-10-29): the file and the company's four numbers
   * side by side, the goal catalogue under them across the whole width. In
   * three equal columns the numbers stood one under another, 120px each, and
   * the catalogue was squeezed into a third of the screen.
   */
  /* The period step is one form across the width. */
  .setup-step-donem { grid-template-columns: minmax(0, 1fr); }
  /*
   * THE STEP DOES NOT SCROLL (2026-10-29): three tabs - the file, the chains,
   * the catalogue. The open tab's card is as tall as what it holds, at most
   * the step; past that only its table scrolls, its head row standing, the
   * catalogue's save at the card's foot.
   */
  .setup-pane .pane-body:has(> .setup-step-calisanlar) { overflow: hidden; display: flex; flex-direction: column; }
  .setup-step-calisanlar { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .setup-step-calisanlar > .tab-set { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; }
  .setup-step-calisanlar > .tab-set > .tab-bar { flex: none; align-self: flex-start; }
  .setup-step-calisanlar .tab-panel:not([hidden]) { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .setup-step-calisanlar .tab-panel > .card { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; margin: 0; }
  /* The tab's name is the card's title (and its count): the card does not say it twice. */
  .setup-step-calisanlar .tab-panel > .card > .card-head { display: none; }
  .setup-step-calisanlar .tab-panel > .card > .card-body { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; overscroll-behavior: contain; }
  .setup-step-calisanlar .tab-panel > .card > .card-body > * { flex: none; }
  .setup-step-calisanlar .chain-table { flex: 0 1 auto !important; min-height: 0; display: flex; flex-direction: column; margin-top: 12px; }
  .setup-step-calisanlar .chain-table > .scroll-x { flex: 0 1 auto; min-height: 0; overflow: auto; }
  .setup-step-calisanlar .chain-table thead th { position: sticky; top: 0; z-index: 1; background: var(--surface); }
  #catalogue-panel > .card-body > .catalogue-form { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
  #catalogue-panel .catalogue-form > .scroll-x { flex: 0 1 auto; min-height: 0; overflow: auto; border: 0; }
  #catalogue-panel .catalogue-table thead th { position: sticky; top: 0; z-index: 1; background: var(--surface); }
  .setup-pane .setup-step-body #catalogue-panel .catalogue-form > .form-actions:last-child { flex: none; margin: 0; padding: 10px 16px; }
  /* The letters' step: the bonus mapping and the grade access, two halves of the width. */
  .setup-step-harf { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* The five letters' coefficients in one row: a letter is a short box. */
  .bonus-panel .form-row { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
}
@media (min-width: 1101px) and (min-height: 600px) {
  /* Who to add, why, and the button: one row over the list of those added. */
  #grade-access form[action="/performance/grades/access"] { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 10px; align-items: end; }
  #grade-access form[action="/performance/grades/access"] .form-row { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 8px; }
  /* A button at the end of the row, not a form's closing bar: no rule over it. */
  .setup-pane .setup-step-body #grade-access form[action="/performance/grades/access"] > .form-actions { margin: 0; padding: 0; border-top: 0; }
}

/* A tab holding one panel: the tab already says its name. A head with buttons or counts stays. */
/* (Only of its type: the "Aşağıda devamı var" button the script adds is a div, not a panel.) */
.tab-pane-frame .tab-panel > section.card:only-of-type > .card-head:not(:has(.row)) { display: none; }
@media (min-width: 1101px) and (min-height: 600px) {
  .quota-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
  .quota-split > * { min-width: 0; }
  .quota-bars { border-left: 1px solid var(--border-subtle); }
  .quota-edit .form-actions { margin-top: 0; }
}

@media (min-width: 1101px) and (min-height: 600px) {
  .user-form { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 12px 24px; align-items: start; }
  .user-form > * { min-width: 0; margin: 0; }
  .user-form-main, .user-form-side { display: grid; gap: 12px; }
  .user-form-save { grid-column: 1 / -1; }
}

@media (min-width: 1101px) and (min-height: 600px) {
  /* Görünüm: the six choices two by two, each its name over its tiles. */
  .appearance-card .setting-rows { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; }
  .appearance-card .setting-row { grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 12px 18px; border-top: 1px solid var(--border-subtle); }
  .appearance-card .setting-row:nth-child(-n+2) { border-top: 0; }
  .appearance-card .setting-row:nth-child(odd) { border-right: 1px solid var(--border-subtle); }
  /* A new request: the five kinds in one row, the form under them. */
  .tk-new .sup-cats-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .tk-new .sup-cat-hint { font-size: var(--fs-2xs); }
}
@media (min-width: 1101px) and (min-height: 600px) {
  /* Each choice's options in one row: a smaller picture of the same screen. */
  .appearance-card .radio-group-tiles .radio-option { width: 100px; padding: 6px 6px 7px; }
  .appearance-card .radio-group-tiles .mini-ui, .appearance-card .radio-group-tiles .mini-ui-split,
  .appearance-card .radio-group-tiles .mini-font, .appearance-card .radio-group-tiles .mini-hero,
  .appearance-card .radio-group-tiles .mini-arrive { width: 86px; height: 50px; }
  .appearance-card .setting-row-head p { line-height: 1.4; }
}
@media (min-width: 1101px) and (min-height: 600px) {
  /* A new request on one screen: the kinds' hints one line, the boxes a size down. */
  .tk-new .card-head { padding: 12px 18px; }
  .tk-new .card-body { padding: 12px 18px; }
  .tk-new .sup-new-form { gap: 10px; }
  .tk-new .sup-cat { padding: 8px 10px; }
  .tk-new .sup-cat-hint { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .tk-new textarea.control { height: 96px; min-height: 72px; }
}
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  /* The chain in one line a chip: role, name, marks. */
  .desk-card .chain-strip .person-chip { display: flex; align-items: center; gap: 6px; white-space: nowrap; overflow: hidden; padding: 4px 8px; }
  .desk-card .chain-strip .person-chip .label { display: inline; margin: 0; font-size: 12px; }
  .desk-card .chain-strip .person-chip strong { font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; }
  .desk-card .chain-strip .person-chip .badge { font-size: var(--fs-2xs); padding: 1px 5px; }
  .karne-pane section.status { padding-top: 8px; padding-bottom: 8px; }
}

/* The sheet being typed: the title box the room, the type and the weight what they need. */
@container (max-width: 960px) {
  .goal-entry-form .goal-type { width: 150px; min-width: 150px; }
  .goal-entry-form .goal-weight { width: 84px; }
  .goal-entry-form .goal-detail { width: 26%; }
}
/* The totals' rule on the totals' line. */
.desk-card .goal-grid tr.total .total-rule { display: inline; margin: 0 0 0 10px; }
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  /* Scoring on a short screen: the five meanings one line each, a goal's
     type and description one line under its title. */
  .desk-card .legend-strip-cols li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
  .desk-card .goal-grid .goal-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .desk-card .score-entry-form .card-foot { display: none; }
}
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  /* A page that is a column of panels: the same air, a size smaller. */
  .main.is-flow, .page-bar + .main.is-flow { padding: 12px 16px; }
  .main.is-flow > * + * { margin-top: 12px; }
  .main.is-flow .card-head { padding-top: 12px; padding-bottom: 12px; }
  .main.is-flow .card-body { padding-top: 14px; padding-bottom: 14px; }
}
@media (min-width: 1101px) and (min-height: 600px) {
  .applied-split:has(> :nth-child(2)) { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr); align-items: start; }
  .applied-split > * { min-width: 0; }
  .applied-split > :nth-child(2) { border-left: 1px solid var(--border-subtle); }
}

/* A filter applies itself (app.js "every filter applies itself"): its button,
   "Uygula", "Göster", "Çalışanı getir", is only the way without script. */
.js form[method="get"]:not([data-no-auto]):has(select, input[type="search"], input[type="text"]) button[type="submit"]:not([data-keep-visible]) { display: none; }

/* A long table in a tab (Harf Notu's preview, the applied letters): the table
   scrolls in the room the screen leaves, so the button under it - "Harf
   notlarını uygula" - is never pushed below the edge by thirty-five rows. */
@media (min-width: 1101px) and (min-height: 600px) {
  .tab-pane-frame .table-pane .scroll-x { max-height: max(180px, calc(100dvh - 400px)); }
}

/* Toplu kart açma: the period, the filter and the count in the head; the list fills the pane. */
.bulk-filters { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 8px 12px; margin: 0; }
.bulk-filters .field { margin: 0; min-width: 220px; }
.bulk-count { margin: 0 0 8px auto; }
@media (min-width: 1101px) and (min-height: 600px) {
  .pane.is-table > .pane-body > form { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .pane.is-table > .pane-body > form > .scroll-x { flex: 1; min-height: 0; max-height: none; overflow: auto; }
  .main.is-fit > .bulk-pane { flex: 1 1 auto; }
}

/* A card that came back: who sent it, when and why, at the top of the card. */
.desk-returned {
  display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 8px 12px;
  border: 1px solid color-mix(in srgb, var(--warn) 35%, var(--border)); border-left: 4px solid var(--warn);
  border-radius: var(--radius); background: var(--warn-tint); color: var(--text-body); font-size: var(--fs-sm);
}
.desk-returned > svg { flex: none; margin-top: 2px; color: var(--warn-text); }

.grade-warnings { display: flex; gap: 10px; align-items: flex-start; }
.grade-warnings ul { margin: 0; padding-left: 16px; display: grid; gap: 2px; font-size: var(--fs-sm); }
.grade-warnings > svg { flex: none; margin-top: 2px; }

/* A setup form's save button stays at the foot of the step while its fields scroll. */
@media (min-width: 1101px) and (min-height: 600px) {
  .setup-pane .setup-step-body .card { overflow: visible; }
  /* A form's save closes the form: under its last field, at the right, never floating over it. */
  /* Not a person picker's row: there the buttons stand beside the boxes, a field's neighbour (its hidden "Göster" is a submit too). */
  .setup-pane .setup-step-body form:not(.perf-person-picker) > .form-actions:last-child,
  .setup-pane .setup-step-body form:not(.perf-person-picker) > .row:last-child:has(> .btn[type="submit"]) {
    justify-content: flex-end; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-subtle);
  }
}

/* The owner's tools ("Yönetim") are not the step: the step's bar steps aside there. */
.desk-card:has(#kart-yonetim:not([hidden])) .pane-foot { display: none; }
/* The chain: the person whose turn it is is the outlined chip; their name is never cut for a badge. */
.desk-card .chain-strip .person-chip.is-waiting { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.person-chip .label .badge { margin-left: 4px; vertical-align: 1px; font-size: var(--fs-2xs); padding: 0 5px; }

/* The karne's own numbers: the final score and the letter are the page's answer. */
.karne-pane section.status .status-score { font-size: 22px; font-family: var(--font-sans); }
/* The next piece of work's sentence: two lines, never cut mid-word. */
.desk-summary .desk-next-hint { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: normal; }
/* A short screen: the administrator's eighteen links stand without the rail scrolling. */
@media (min-width: 1101px) and (max-height: 820px) {
  .sidebar-brand { padding-top: 12px; }
  .sidebar-brand span { margin-top: 10px; padding-block: 6px; }
  .sidebar-section { padding: 8px 22px 3px; }
  .sidebar-link { padding-block: 4px; font-size: 13px; }
  .sidebar-version { padding-block: 6px; }
}

/* The one-line chain of a short screen: the outlined chip is the turn; the name keeps the room. */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  .desk-card .chain-strip .person-chip .label .badge { display: none; }
}
/* The goal type's full name in the narrow sheet ("Şirket Ortak Hedefi"). */
@container (max-width: 960px) {
  .goal-entry-form .goal-type { width: 188px; min-width: 188px; }
  .goal-entry-form .goal-weight { width: 72px; }
  .goal-entry-form .goal-detail { width: 24%; }
}
/* "Yönetim": stopping or stepping back beside the handover, not one under the other. */
@media (min-width: 1101px) and (min-height: 600px) {
  .desk-card #kart-yonetim:not([hidden]):has(> .card + .card) { display: grid; grid-template-columns: minmax(260px, 2fr) minmax(0, 3fr); gap: 12px; align-items: stretch; }
  .desk-card #kart-yonetim > * + * { margin-top: 0; }
}

/* Geri Bildirim: writing one, received, given - three columns the screen's height. */
.feedback-desk { display: grid; gap: var(--rhythm); }
.feedback-write .pane-body, .feedback-list .pane-body { padding: 14px 16px; }
.feedback-write .col { gap: 12px; }
.feedback-list .desk-sheet-head { margin: 0; }
.feedback-desk .pane-head { min-height: 56px; justify-content: center; }
@media (min-width: 1101px) and (min-height: 600px) {
  /* Three panes side by side end on one line, as the work desk's two do (.ws). */
  .feedback-desk {
    flex: 1 1 auto; min-height: 0; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 12px;
    grid-template-rows: minmax(0, 1fr); align-items: stretch;
  }
  .feedback-desk > * { max-height: 100%; }
}

/* Bildirimler: the list the screen's height. */
@media (min-width: 1101px) and (min-height: 600px) {
  .main.is-fit > .notices-card { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .notices-card > .card-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .notices-card .bell-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .notices-card .bell-scroll { flex: 1; min-height: 0; height: auto; }
}
/* A short admin page laid out in two columns. */
.admin-grid { display: grid; gap: var(--rhythm); }
.admin-grid > * { margin: 0 !important; min-width: 0; }
/* Cards in a row are one height; the small number tiles keep their own. */
@media (min-width: 1101px) { .admin-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; } .admin-grid > .metrics { align-self: start; } }

/* -- 16:9 screens: what fills the screen fills it (2026-10-28) ------------------------ */
@media (min-width: 1101px) and (min-height: 600px) {
  /* A tab whose panel is a table: the table takes the room the screen leaves and scrolls in it. */
  .tab-pane-frame .pane-body:has(> .tab-panel:not([hidden]) > .card > .card-body > .table-pane) {
    display: flex; flex-direction: column; overflow: hidden;
  }
  .tab-pane-frame .pane-body > .tab-panel:not([hidden]):has(> .card > .card-body > .table-pane) { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .tab-pane-frame .tab-panel:has(> .card > .card-body > .table-pane) > .card { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .tab-pane-frame .tab-panel:has(> .card > .card-body > .table-pane) > .card > .card-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .tab-pane-frame .tab-panel > .card > .card-body > .table-pane { flex: 1; min-height: 140px; display: flex; flex-direction: column; }
  .tab-pane-frame .tab-panel > .card > .card-body > .table-pane > .scroll-x { flex: 1; min-height: 0; max-height: none; }
  /* The org chart: its drawing takes the room under the filters. */
  .tab-pane-frame .pane-body:has(> #chart:not([hidden])) { display: flex; flex-direction: column; overflow: hidden; }
  .tab-pane-frame .pane-body > #chart:not([hidden]) { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  #chart > .org-drawn { flex: 1; min-height: 0; overflow: auto; }
}


/* A goal row not yet asked for: on the page, out of sight until "Hedef ekle". */
.goal-grid tr[data-goal-spare][hidden], [data-goal-add][hidden] { display: none; }
.goal-entry-form > .card-foot, .desk-sheet .goal-entry-form .card-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.goal-entry-form [data-goal-add] { order: -1; }
.goal-entry-form .card-foot > .card-note:first-of-type { margin-right: auto; }

/* A slot a search fills in place (app.js data-swap): no box of its own in the layout. */
.swap-slot { display: contents; }
.topbar-slot:empty { display: none; }

/* Whether the person can sign in, beside the heading where it is settled. */
.perf-assignment-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
/* The card's reassignment: the source, then the three people in one row. */
.reassign-form > * + * { margin-top: 10px; }
.reassign-people { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.reassign-people > * { margin: 0; min-width: 0; }
@media (max-width: 1100px) { .reassign-people { grid-template-columns: minmax(0, 1fr); } }
@media (min-width: 1101px) and (min-height: 600px) {
  /*
   * Uygulanan: the letters and the correction side by side, each the pane's
   * height and scrolling in itself - the list was cut at half height over an
   * empty strip while the correction pushed the whole tab into a second scroll.
   */
  .tab-pane-frame .pane-body:has(> .tab-panel:not([hidden]) > .card > .card-body > .applied-split) {
    display: flex; flex-direction: column; overflow: hidden;
  }
  .tab-pane-frame .pane-body > .tab-panel:not([hidden]):has(> .card > .card-body > .applied-split),
  .tab-pane-frame .tab-panel:has(> .card > .card-body > .applied-split) > .card,
  .tab-pane-frame .tab-panel:has(> .card > .card-body > .applied-split) > .card > .card-body {
    flex: 1; min-height: 0; display: flex; flex-direction: column;
  }
  .tab-pane-frame .card-body > .applied-split { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr); align-items: stretch; }
  .tab-pane-frame .applied-split > .table-pane { display: flex; flex-direction: column; min-height: 0; }
  .tab-pane-frame .applied-split > .table-pane > .scroll-x { flex: 1; min-height: 0; max-height: none; }
  .tab-pane-frame .applied-split > :nth-child(2) { min-height: 0; overflow: auto; }
}

/* The desk list's "no match": a box of its own, not a line the eye slides past. */
.desk-none { padding: 12px; }
.desk-none[hidden] { display: none; }

/* -- a person picked by typing (app.js data-combo) --------------------------------- */
.combo { position: relative; }
.combo .combo-native { display: none; }
.combo-input { width: 100%; padding-right: 36px; }
.combo-clear {
  position: absolute; top: 50%; right: 8px; transform: translateY(-50%);
  display: grid; place-items: center; width: 22px; height: 22px; padding: 0;
  border: 0; border-radius: 50%; background: var(--surface-sunken); color: var(--text-muted);
  font-size: 15px; line-height: 1; cursor: pointer;
}
.combo-clear:hover { background: var(--surface-hover); color: var(--text-body); }
.combo-clear[hidden] { display: none; }
.combo-list {
  position: fixed; z-index: 1200; margin: 0; padding: 4px; list-style: none; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-overlay);
  overscroll-behavior: contain;
}
.combo-list[hidden] { display: none; }
.combo-count { padding: 6px 10px 4px; color: var(--text-muted); font-size: var(--fs-xs); font-weight: 600; }
.combo-none { padding: 12px 10px; color: var(--warn-text); font-size: var(--fs-sm); font-weight: 600; }
.combo-option { display: flex; flex-direction: column; gap: 1px; padding: 8px 10px; cursor: pointer; }
.combo-option:hover, .combo-option.is-active { background: var(--surface-hover); }
.combo-option[aria-selected="true"] { background: var(--surface-selected); }
.combo-option[aria-selected="true"] .combo-main::after { content: " ✓"; color: var(--accent-text); }
.combo-main { color: var(--text-body); font-weight: 600; }
.combo-sub { color: var(--text-muted); font-size: var(--fs-xs); }
.combo-option mark { padding: 0; background: none; color: var(--accent-text); font-weight: 800; }

/*
 * THE NOTICE NEVER LIES OVER WHAT IS PRESSED (2026-10-28). In the bottom
 * right it sat on the card's own buttons - "Hedefleri kaydet", "Kaydet ve
 * onaya gönder", "Sonraki adım", "Kartları aç" - for its seven seconds, and a
 * second press landed on the notice; under a resting pointer its fade-in was
 * paused at the first frame, so it covered the buttons invisibly. It now
 * comes down at the top right, under the top bar, lets every click through
 * but its own ×, and hovering holds only its leaving, never its arrival. A
 * refusal stays longer: it is the one that has to be read.
 */
.toast-region { inset-block-start: 80px; inset-block-end: auto; }
.toast { pointer-events: none; }
.toast-close { pointer-events: auto; }
.toast:hover, .toast:focus-within { animation-play-state: running, paused; }
.toast-error { --toast-hold: 11s; }
@media (max-width: 580px) {
  .toast-region { inset-block-start: 68px; inset-block-end: auto; }
}
/* "Hepsini göster" lands on a row: it stands under the table's own sticky head, not behind it. */
.table-pane tr[id] { scroll-margin-top: 48px; }
/*
 * THE WEIGHT IS NEVER CUT (2026-10-28): at 1536 the narrow sheet ran 6px wide
 * and the weight box showed "2(" for 25 behind a sideways scroll. Tighter
 * cells, a weight column that holds "AĞIRLIK %" and two digits, no spinner.
 */
@container (max-width: 960px) {
  .goal-entry-form .goal-grid th, .goal-entry-form .goal-grid td { padding-inline: 8px; }
  .goal-entry-form .goal-type { width: 172px; min-width: 172px; }
  .goal-entry-form .goal-weight { width: 88px; }
  .goal-entry-form .goal-detail { width: 23%; }
}
.goal-entry-form .goal-weight input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
.goal-entry-form .goal-weight input[type="number"]::-webkit-inner-spin-button,
.goal-entry-form .goal-weight input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/*
 * ON A PHONE A WIDE TABLE SCROLLS, IT IS NOT CUT (2026-10-28). A tab's
 * panel was a grid with no column template, so its card grew to the
 * table's width, the table's own sideways scroll never engaged, and the
 * pane cut the rest: the karne lost AĞIRLIK, NOT and PUAN, Planlar its
 * dates, Harf Notu and the ledger their right-hand columns. The panel's one
 * column is the panel's width; so are the settings step's cards.
 */
.tab-panel { grid-template-columns: minmax(0, 1fr); }
.tab-panel > *, .setup-step-body > *, .stack > .card { min-width: 0; max-width: 100%; }

/* -- the phone, as the sweep found it (2026-10-28) ------------------------------------ */
@media (max-width: 760px) {
  /* The board's phases and counts: two to a row, not four squeezed to "HAZIRL" and "3 / 3". */
  .desk-summary .phase-strip, .desk-summary .pano-overview .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* "Sıradaki işiniz": its sentence whole, the button under it, not a 97px column. */
  .desk-next { flex-wrap: wrap; }
  .desk-next-text { flex-basis: 100%; }
  .desk-summary .desk-next-hint { display: block; -webkit-line-clamp: unset; overflow: visible; white-space: normal; }
  /* The card's buttons after its work, with their whole sentence: stuck to the screen they hid the chain and the tabs. */
  .desk-card .pane-foot { position: static; }
  .action-bar-say { display: block; -webkit-line-clamp: unset; overflow: visible; }
}
@media (max-width: 1100px) {
  /* "Bu sayfada ne yapılır?" open: the head stays under the top bar, so the bell and the menu stay in reach. */
  .page-head:has(.page-help[open]) { z-index: 15; }
}

/* A new request's kinds where the tiles are narrow: the names in them, the chosen sentence under them. */
.sup-cat-said { margin: 6px 0 0; font-size: var(--fs-sm); color: var(--text-secondary); }
.sup-cat-said:empty { display: none; }
@media (min-width: 1701px) { .sup-cat-said { display: none; } }
@media (min-width: 1101px) and (max-width: 1700px) {
  .js .tk-new .sup-cat-hint { display: none; }
}
@media (max-width: 1100px) { .sup-cat-said { display: none; } }

.tab-bar[hidden] { display: none !important; }

/* A tab's rows stand at its top: stretched to the pane's height they opened bands between them. */
.tab-panel { align-content: start; }
/* The panel's own gap spaces its parts; their margins came on top of it (a 38px band under the 1–5 key). */
.tab-panel > * { margin-top: 0; margin-bottom: 0; }
/*
 * NO BLACK FRAME ROUND A PANEL (2026-10-28). A tab or a section the address
 * names is focused on arrival so the keyboard starts there; with nothing
 * pressed yet the browser counted that as keyboard focus and drew its ring
 * round the whole panel. A place to start from is not a control: no ring.
 */
[tabindex="-1"]:focus, [tabindex="-1"]:focus-visible { outline: none; }
/*
 * The reason box one line of the larger type, without a scroll of its own -
 * AND THE BUTTONS' HEIGHT (2026-10-29): at its own height it stood 2px taller
 * than the buttons beside it, and a step with a reason box had a taller
 * action bar than the step before it.
 */
.action-bar-note .control { display: block; height: var(--control-h); min-height: var(--control-h); padding: 8px 10px; line-height: 1.35; }
/* The desk list's two filters: the department gets the room it needs ("Tüm departmanlar" whole). */
.desk-filter-row { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
.desk-filter-row .control { padding-inline: 10px 26px; text-overflow: ellipsis; }

@media (max-width: 760px) {
  /* The page's help on a phone: a sheet under the top bar, the screen's width (it ran 55px off the right). */
  .page-help-panel { position: fixed; top: 68px; left: 12px; right: 12px; width: auto; margin: 0; max-height: calc(100dvh - 84px); overflow-y: auto; z-index: 60; }
  /* The step's way through, one button under the other: side by side they ran past the edge. */
  .step-nav { flex-wrap: wrap; }
  .step-nav .btn, .step-nav > span, .step-nav-end { flex: 1 1 100%; }
  .step-nav-end { flex-wrap: wrap; }
  .step-nav > span:empty { display: none; }
}
/* A chain chip: the name shortens, its "SİZ" stays whole beside it. */
.person-chip strong { display: flex; align-items: center; gap: 6px; min-width: 0; }
.person-chip .chip-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.person-chip strong > .badge { flex: none; }
.desk-card .chain-strip .person-chip strong { overflow: visible; }
/* The five meanings whole on a short screen: two lines where one does not hold them (they were cut by a word). */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  .desk-card .legend-strip-cols li { white-space: normal; overflow: visible; text-overflow: clip; display: flex; }
}

/* A phone's top bar: the page's name; the module's name above it was cut to "PERFORMANS YÖNETİ…". */
@media (max-width: 760px) { .topbar-title > span:first-child { display: none; } }

/* The company goals' editor (Ayarlar → Referans verisi): the step's whole width, the boxes in their cells. */
.setup-step-body > #catalogue-panel { grid-column: 1 / -1; }
.catalogue-table td { padding-block: 6px; vertical-align: middle; }
.catalogue-table .control { width: 100%; }
/* One line here, as a box in a row; on a phone it grows to hold the whole sentence (below). */
.catalogue-table textarea.control { display: block; height: var(--control-h); min-height: var(--control-h); padding-block: 8px; resize: none; overflow: hidden; white-space: nowrap; }
/* Three digits in sight: at 76px a number box showed "10" as "1" (2026-10-30). */
.catalogue-table .catalogue-order { width: 96px; }
.catalogue-table .catalogue-order .control { padding-inline: 10px; text-align: center; }
.catalogue-table .catalogue-remove { width: 96px; text-align: center; }
.catalogue-table tr.catalogue-spare .control { background: var(--surface-sunken); }
/* On a phone a goal is a block, not a row: four columns left the title's box 37px wide. */
@media (max-width: 640px) {
  .catalogue-table, .catalogue-table tbody { display: block; }
  .catalogue-table thead { display: none; }
  .catalogue-table tr { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 8px; padding: 12px; border-bottom: 1px solid var(--border-subtle); }
  .catalogue-table td { display: block; width: auto; min-width: 0; padding: 0; border: 0; }
  .catalogue-table td[data-label]::before { content: attr(data-label); display: block; margin-bottom: 4px; color: var(--text-secondary); font-size: var(--fs-xs); font-weight: 600; }
  .catalogue-table .catalogue-title, .catalogue-table .catalogue-detail { grid-column: 1 / -1; grid-row: auto; }
  .catalogue-table textarea.control { height: auto; field-sizing: content; white-space: normal; }
  .catalogue-table .catalogue-remove { grid-column: 2; grid-row: 1; align-self: end; width: auto; text-align: right; }
  :is(#kart-ilerleme, #grade-access) .table, :is(#kart-ilerleme, #grade-access) .table tbody, :is(#kart-ilerleme, #grade-access) .table td { display: block; width: auto; }
  :is(#kart-ilerleme, #grade-access) .table thead { display: none; }
  :is(#kart-ilerleme, #grade-access) .table tr { display: block; position: relative; padding: 10px 56px 10px 12px; border-bottom: 1px solid var(--border-subtle); }
  #grade-access .table tr { padding-right: 112px; }
  :is(#kart-ilerleme, #grade-access) .table td { padding: 2px 0; border: 0; }
  :is(#kart-ilerleme, #grade-access) .table td.col-remove { position: absolute; top: 8px; right: 8px; padding: 0; }
}
/* "Hedef ekle" where the rows end, "Kataloğu kaydet" where the form is done (an id: the setup step's foot rule is longer). */
#catalogue-panel form.catalogue-form > .form-actions:last-child { justify-content: space-between; }

/* Taking a person off the list: the grid's whole width, the words left and the button right. */
.perf-assignment-grid > section.perf-remove-employee {
  grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
.perf-remove-employee h3 + p { margin-bottom: 0; }
/* Adding one: folded under the picker, below the empty state. */
#assignment-panel #add-employee { margin-top: 14px; }
.perf-add-employee > * + * { margin-top: 12px; }

/* The test site's five scenario sets, in the line over the period form (test-site.ts). */
.test-site-sets { display: flex; flex-wrap: wrap; gap: 6px; margin-left: auto; }
.test-site-sets .confirm-pop { width: min(380px, 80vw); right: 0; left: auto; }

/* The test site's mark (test-site.ts): bottom left on every page, over the rail's footer; never on the real site. */
/*
 * IN THE RAIL'S OWN VOICE (2026-10-29): it was a yellow block over the rail's
 * foot, the loudest thing on every screen. Now a quiet band in the rail just
 * above the version line - the rail's white on a darker wash of its own red,
 * a dot for the eye - and plain text at the foot of the sign-in page.
 */
.test-site-mark {
  margin: auto 14px 0; padding: 7px 10px 7px 26px; position: relative;
  border-radius: var(--radius); border: 1px solid rgb(255 255 255 / .22);
  background: rgb(0 0 0 / .22); color: rgb(255 255 255 / .9);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.35;
}
.test-site-mark::before {
  content: ""; position: absolute; left: 11px; top: 50%; width: 7px; height: 7px; margin-top: -3.5px;
  border-radius: 50%; background: rgb(255 255 255 / .85);
}
.test-site-mark + .sidebar-version { margin-top: 0; }
body > .test-site-mark {
  margin: 0; position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%);
  border-color: var(--border); background: var(--surface); color: var(--text-secondary);
}
body > .test-site-mark::before { background: var(--text-muted); }

/*
 * A SHORT SCREEN (a 1366x768 laptop): the setup steps still do not scroll.
 * The period card's own title says what the step bar above already says,
 * and its rows close up; the form keeps every field and every hint.
 *
 * UP TO 960px TALL, NOT 800 (2026-10-29): a 1920x1080 screen with the
 * browser's bars leaves about 900px, and there the period card scrolled 38px
 * inside itself - "her şey sayfaya sığacak".
 */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 960px) {
  .setup-step-donem #period-panel > .card-head { display: none; }
  .setup-step-donem #period-panel .form-row { row-gap: 6px; margin-bottom: 8px; }
  .setup-step-donem #period-panel form > :last-child { margin-bottom: 0; }
  .setup-step-donem #period-panel .field-hint { margin-top: 2px; line-height: 1.35; }
}
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 800px) {
  .setup-pane .setup-step-body > .setup-note { padding: 6px 12px; }
}

/*
 * A STEP NEVER SCROLLS AS ONE (2026-10-29). Where a step holds more than the
 * screen (a short laptop screen, a person's whole chain open), each card
 * scrolls inside its own body - its title and the step's way through stay -
 * instead of the whole step sliding under the bar. On a screen it fits,
 * nothing scrolls at all.
 */
@media (min-width: 1101px) and (min-height: 600px) {
  .setup-pane > .pane-body:has(> .setup-step-body:not(.setup-step-calisanlar)) { overflow: hidden; display: flex; flex-direction: column; }
  .setup-step-body:not(.setup-step-calisanlar) { flex: 0 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); }
  .setup-step-body:not(.setup-step-calisanlar):has(> .setup-note) { grid-template-rows: auto minmax(0, 1fr); }
  .setup-step-body:not(.setup-step-calisanlar) > * { min-height: 0; }
  .setup-step-body:not(.setup-step-calisanlar) > .card { display: flex; flex-direction: column; }
  .setup-step-body:not(.setup-step-calisanlar) > .card > .card-head { flex: none; }
  .setup-step-body:not(.setup-step-calisanlar) > .card > .card-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
}
/* A short screen: the number tiles close up, so a page of them and two groups stays on it (Sistem Sağlığı). */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 800px) {
  .metric { padding: 12px 16px; }
  .metric .value { font-size: var(--fs-xl); }
}
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 800px) {
  .main.is-flow, .page-bar + .main.is-flow { padding: 10px 14px; }
  .main.is-flow > * + * { margin-top: 10px; }
}
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 800px) {
  .main > .status { padding: 12px 18px; }
}
/* The evidence tab's two columns start on one line (the right one's first group was spaced as a follower). */
.desk-context > .labelled-group:nth-child(-n+2) { padding-top: 0; border-top: 0; }
/* A 1–5 choice and a short note do not need the whole width. */
.desk-context .labelled-group select, .desk-context .labelled-group input[type="text"], .desk-context .labelled-group input:not([type]) { max-width: 520px; }
/* The card's way out, at the end of its title row (the phone has "‹ Liste" instead). */
.desk-close { margin-left: auto; align-self: center; display: inline-flex; align-items: center; gap: 4px; padding: 4px 8px; border-radius: var(--radius); font-size: var(--fs-sm); color: var(--text-secondary); text-decoration: none; }
.desk-close:hover { background: var(--surface-hover); color: var(--text-body); }
@media (max-width: 1100px) { .desk-close { display: none; } }
/* The potential's short form ends where its boxes do, its save under their right edge. */
.desk-context .labelled-group form { max-width: 520px; }
/*
 * THE VERSION IN USE, ON ONE LINE OF THE HEAD (2026-10-29): three stacked
 * lines in a box ran out of the 60px bar and were cut at the top of the screen.
 */
.page-bar .release-now {
  display: inline-flex; align-items: baseline; gap: 8px; padding: 6px 12px; text-align: left;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); box-shadow: none;
}
.page-bar .release-now-version { font-size: var(--fs-sm); }
/* A plan: what it is on the left, what can be done to it on the right. */
.plan-layout { display: grid; gap: 12px; }
.plan-layout > div { display: grid; gap: 12px; align-content: start; min-width: 0; }
.plan-layout .card { margin: 0; }
@media (min-width: 1101px) { .plan-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); align-items: start; } }
/*
 * A PAGE WITHOUT ITS OWN HEAD (a request's conversation) has the same head as
 * every other (2026-10-29): one line, the same size and height - not
 * "PotentiaX" over the subject in a taller bar.
 */
@media (min-width: 1101px) and (min-height: 600px) {
  .main-col:not(:has(> .page-bar)) > .topbar { height: 60px; }
  .topbar-title > span { display: none; }
  .topbar-title strong { font-size: 19px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.25; }
  .topbar-title::before { height: 30px; }
}
/* A short screen: every page's bar 56px, with or without a page bar (no 4px jump between pages). */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  .main-col:not(:has(> .page-bar)) > .topbar { height: 56px; }
  .topbar-title strong { font-size: 17px; }
  .topbar-title::before { height: 28px; }
}
/* A request's subject in the list goes on a second line rather than being cut. */
.sup-item-subject { white-space: normal; overflow-wrap: anywhere; }
/* A narrower screen: the manage tab's two cards one under the other, so the hand-over's three person boxes have room. */
@media (max-width: 1500px) {
  .desk-card #kart-yonetim:not([hidden]):has(> .card + .card) { grid-template-columns: minmax(0, 1fr); }
}
/* The peer form's 1–5 choice is a short box, not the screen's width. */
form[action^="/performance/review/"] select { max-width: 360px; }
/* A plan its reader cannot change: no right column, the plan across the width. */
@media (min-width: 1101px) { .plan-layout:not(:has(> .plan-main > .card)) { grid-template-columns: minmax(0, 1fr); } }
.plan-layout > .plan-main:not(:has(> .card)) { display: none; }
/* The test site: the list's own person under a chain slot the tester stands in. */
.chain-really { display: block; margin-top: 2px; white-space: nowrap; }
.chain-table td:has(.chain-really), .chain-table tr:has(.chain-really) > td { vertical-align: top; }
/*
 * The chain's one-line chips on a short screen: a note ("tanımsız" and the
 * like) stays ON THE LINE, after the name (2026-10-29). On a line of its own
 * it made that card's chain 81px against the next card's 32, and the tabs
 * and the sheet under it moved from person to person. The note gives way
 * before the name does. Only the test site's stand-in, a whole name on every
 * chip, takes the line under it (.is-under).
 */
@media (min-width: 1101px) and (min-height: 600px) and (max-height: 880px) {
  .desk-card .chain-strip .person-chip > .label { height: auto; }
  .desk-card .chain-strip .person-chip strong { min-width: 0; flex: 0 1 auto; }
  .desk-card .chain-strip .person-chip .person-chip-note { display: inline; margin: 0; min-width: 0; flex: 0 10 auto; overflow: hidden; text-overflow: ellipsis; }
  .desk-card .chain-strip .person-chip:has(.is-under) { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 6px; align-items: center; }
  .desk-card .chain-strip .person-chip:has(.is-under) strong { overflow: hidden; justify-content: flex-start; }
  .desk-card .chain-strip .person-chip .person-chip-note.is-under { display: block; grid-column: 1 / -1; }
}
/* A card too narrow for eight named steps: the steps after the next keep their number only. */
@container deskcard (max-width: 960px) {
  .desk-card .step-tracker-item.is-current + .step-tracker-item ~ .step-tracker-item .step-tracker-label,
  .desk-card .step-tracker-item.is-current + .step-tracker-item ~ .step-tracker-item .step-tracker-note { display: none; }
}
/* Taking something back: a row's trash button, quiet until pointed at. */
.remove-form { display: inline-flex; margin: 0; }
.remove-form .btn-icon { color: var(--text-secondary); }
.remove-form .btn-icon:hover { color: var(--error-text); }
.col-remove { width: 48px; text-align: center; }
.quote-meta:has(.quote-action) { display: flex; align-items: center; gap: 8px; }
.quote-action { margin-left: auto; }
/* A period with nothing in it: its delete under the form, the sentence on the left. */
.period-delete { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border-subtle); }
