/*
 * Design tokens — the single source for colour, spacing, typography, and radius.
 * Every stylesheet and template consumes these; nothing else restates the values.
 *
 * The palette is the Next.js prototype's (`hamagakuen-ai-edu`, `src/app/globals.css`
 * `:root`) — the UI the school chose at the demo on 2026-08-03 (ADR-020 §Decision 2).
 * That supersedes both seeds this file carried before: the Microsoft Fluent 2 ramp
 * (ADR-011, issue #29) and the Hamagakuen logo blue #0395DA (client, 2026-07-30).
 * Values are copied, never re-derived; the only permitted difference is a WCAG AA
 * nudge, and every one records the prototype's original value and the measured
 * ratio at the token (ADR-020 §Decision 3).
 *
 * Every ratio below names its reference background, because the prototype has two:
 * the page --background #f8fafc and the raised surface --card-bg #ffffff. WCAG 2.1
 * AA thresholds: 4.5:1 for body text, 3:1 for large text and for the boundaries
 * that identify a control.
 *
 * The type / spacing / layout scales at the bottom are still the Fluent ones. They
 * are not colour and nothing about them was rejected on 2026-08-03; every
 * hand-written stylesheet consumes them, so they retire with their last reference,
 * not here. The colour bridge and the Fluent radius ramp reached zero references in
 * the sweep (#137) and are gone.
 */

/*
 * Noto Sans JP, self-hosted. --font-family-base has named it since #29 while
 * nothing ever shipped it, so every screen has been rendering in the Hiragino /
 * Yu Gothic fallback (issue #128). Nothing is fetched from fonts.googleapis.com
 * or fonts.gstatic.com at runtime: ADR-006 vendors front-end assets as pinned real
 * files, and a third-party font request from a screen that renders PII of minors
 * would hand that third party the page view as well.
 *
 * Source:  google/fonts @ 66a36c8c94b1a5d992ee4e7f392fccfe4945767c —
 *          ofl/notosansjp/NotoSansJP[wght].ttf, the release Google Fonts serves as
 *          css2 v56. Version 2.004 (the font's own name ID 5) is what the
 *          filenames pin.
 * Licence: SIL Open Font License 1.1 — ../vendor/fonts/OFL.txt, and recorded with
 *          the other vendored assets in docs/project-config.md §9.
 * Built:   the variable font instanced at each weight, then subset to woff2. The
 *          exact commands are in git履歴（scratchpad 廃止前のコミット）.
 *          That is not a build step — ADR-020 licenses exactly one and it is
 *          Tailwind's; these six committed files are the artefact.
 *
 * Two files per weight, split on Google's own latin unicode-range, so a screen
 * with no Japanese glyph downloads 14 KB instead of 1.1 MB. The two ranges are
 * disjoint and a test asserts it, because the split is only worth having if it is.
 *
 * The japanese files carry CP932 (Windows-31J: JIS X 0208 plus the NEC/IBM
 * extensions — so 髙 / 﨑 / 德 in a student's name are the real typeface, not the
 * fallback) plus the symbol blocks these screens use. The declared U+4E00-9FFF is
 * deliberately wider than the file: unicode-range chooses which FILE to download,
 * and spelling out all 8,410 codepoints here would be unreadable. A kanji rarer
 * than CP932 falls through to the next family in --font-family-base, which is
 * where every kanji renders today.
 */

@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../vendor/fonts/noto-sans-jp-2.004-400-latin.1c78b3f0116a.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../vendor/fonts/noto-sans-jp-2.004-400-japanese.cf18514fafaa.woff2") format("woff2");
  unicode-range: U+0370-03FF, U+0400-04FF, U+2100-2121, U+2123-2190, U+2192,
    U+2194-2211, U+2213-2214, U+2216-23FF, U+2460-24FF, U+2500-257F, U+25A0-25FF,
    U+2600-26FF, U+2700-27BF, U+3000-30FF, U+31F0-31FF, U+3200-33FF, U+4E00-9FFF,
    U+F900-FAFF, U+FF00-FFEF;
}

@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../vendor/fonts/noto-sans-jp-2.004-500-latin.1561ad4cbf2c.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../vendor/fonts/noto-sans-jp-2.004-500-japanese.c074526eec43.woff2") format("woff2");
  unicode-range: U+0370-03FF, U+0400-04FF, U+2100-2121, U+2123-2190, U+2192,
    U+2194-2211, U+2213-2214, U+2216-23FF, U+2460-24FF, U+2500-257F, U+25A0-25FF,
    U+2600-26FF, U+2700-27BF, U+3000-30FF, U+31F0-31FF, U+3200-33FF, U+4E00-9FFF,
    U+F900-FAFF, U+FF00-FFEF;
}

@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../vendor/fonts/noto-sans-jp-2.004-700-latin.bea3679ed581.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Noto Sans JP";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../vendor/fonts/noto-sans-jp-2.004-700-japanese.396b6d7f4ef8.woff2") format("woff2");
  unicode-range: U+0370-03FF, U+0400-04FF, U+2100-2121, U+2123-2190, U+2192,
    U+2194-2211, U+2213-2214, U+2216-23FF, U+2460-24FF, U+2500-257F, U+25A0-25FF,
    U+2600-26FF, U+2700-27BF, U+3000-30FF, U+31F0-31FF, U+3200-33FF, U+4E00-9FFF,
    U+F900-FAFF, U+FF00-FFEF;
}

:root {
  /* The prototype's 12 properties. tools/tailwind/src.css maps these into
     Tailwind's theme with @theme inline, so bg-primary and text-[var(--muted)]
     resolve to the same values the rules below use. */
  /* The PAGE ground, painted once on body (app.css). White since the exams
     flow review (PM, 2026-08-16): the cards on it are separated by a hairline
     --border, so a grey ground under a white card only adds a second edge.
     --background below stayed the faint FILL it also was, because a zebra row,
     a disabled button and a sticky grid head all read it that way. */
  --page-bg: #ffffff;

  /* The faint fill: zebra rows, disabled controls, sticky heads, tab strips.
     Not the page ground any more — that is --page-bg. */
  --background: #f8fafc;
  --card-bg: #ffffff;

  /* 14.03:1 on --background, 14.68:1 on --card-bg. */
  --foreground: #032b43;

  /* 5.24:1 on --background, 5.48:1 on --card-bg. Darker than the slate it
     replaced (4.55 / 4.76) — the same headroom problem, answered rather than
     re-measured every time a background moves. */
  --muted: #5b6b7b;

  /* Navy carries the primary button, the ink, and "you are here". 14.03:1 on
     --background, 14.68:1 on --card-bg; white on it is 14.68:1. */
  --primary: #032b43;
  /* 3.62:1 on --background, 3.79:1 on --card-bg — borders and large text only.
     This is the palette's own blue, unnudged, and it is why it may not be text. */
  --primary-light: #3f88c5;
  --primary-dark: #021d2e;
  /* A neutral tint, not a blue one: the accent fill marks "selected", and a blue
     fill fights the blue that means "a box on the paper". */
  --accent: #eef3f8;

  /* Decorative: card frames, table rules, separators. 1.23:1 on --card-bg, which
     is below 1.4.11's 3:1 — so it is never the boundary that identifies a
     control. That job belongs to --border-strong below. */
  --border: #e1e7ee;

  /* The palette the school picked on 2026-08-16 for this family:
     D00000 · FFBA08 · 3F88C5 · 032B43 · 136F63. The five values are used as
     given wherever they are a FILL, a border or a mark; the only nudges are the
     two that cannot be text on white, and each records its original.

     The three status colours are text (text-[var(--success)] ×30, --danger ×21,
     --warning ×9), so each is held to the 4.5:1 body floor. */
  /* 6.03:1 on --card-bg, 5.76:1 on --background; white on it is 6.03:1. */
  --success: #136f63;
  /* 5.70:1 on --card-bg, and 5.20:1 on its own #fdf2f2 badge fill. */
  --danger: #d00000;
  /* NUDGED. The palette's #ffba08 is 1.71:1 on white — it cannot be a letter.
     #8a6200 is the same hue at the first step that clears the floor: 5.49:1 on
     --card-bg, 5.24:1 on --background, 5.12:1 on its own #fff7dd fill. */
  --warning: #8a6200;
  /* The unnudged #ffba08, for the places warning is a MARK and not a letter:
     the dot on a chip, a card's edge, an input's outline. Text on it is
     --foreground, 8.58:1. */
  --warning-mark: #ffba08;

  /* The palette's blue. A 3.79:1 graphical object (WCAG 1.4.11 wants 3:1): the
     focus ring, a box drawn on a scan, a chart stroke. Never a letter. */
  --blue: #3f88c5;
  /* NUDGED from #3f88c5 for the one place the blue has to be read: a link.
     6.06:1 on --card-bg. */
  --link: #2a669a;

  /* "A teacher has confirmed this" — the sky the school picked for the state a
     question card and its box on the paper share, so one question is one colour
     wherever it appears. 2.13:1 on white: a fill, an edge and a dot, never a
     letter; the label on it is --foreground. --success stays the stepper's
     "this step is done", which is a different sentence. */
  --confirm: #48bfe3;
  --confirm-bg: #eaf7fb;

  /* The focus halo for a control that is ITSELF yellow (a 配点 waiting for its
     number). The global --focus-ring is the blue, which lands as a blue box
     around a yellow one; this keeps the control one colour and marks focus by
     the halo's AREA instead. #ffba08 at 30% — the ring is 3px, so the focused
     state is unmistakable beside an unfocused neighbour even though yellow on
     white is only 1.7:1. */
  --warning-halo: rgba(255, 186, 8, 0.3);

  /* --confirm at 14%. The veil that marks the box the teacher is drawing in
     (exam_setup.css .es__box--active) — the same tint the selected row in a
     list wears, in the sky that means 「この設問はこれ」 everywhere else. Kept
     this thin on purpose: the box frames HANDWRITING, and a fill that reads as
     a colour instead of a hint would sit on top of the thing being framed. */
  --confirm-veil: rgba(72, 191, 227, 0.14);

  /* A card's own edge states it: waiting (the yellow at 45%) or confirmed (the
     sky at 40%). Hairlines, so they sit under 1.4.11's 3:1 on purpose — the
     word in the card says the same thing, and hover raises each to its full
     colour. */
  --line-todo: #ffe090;
  --line-done: #b6e5f4;

  /* The chart series palette — CATEGORICAL, and deliberately not the status
     colours above.

     A line per 科目 walking --success / --danger paints 英語 green and 国語 red,
     and a teacher reads a verdict the data never gave: on this screen the only
     thing separating one 科目 from another is which one it is. The prototype
     keeps its own chart map for exactly this reason
     (dashboard/students/[id] chartColors), and these are its values — the first
     is --primary because the headline series there is 総合.

     Contrast is not measured on these: they are 2px strokes and 4px points, which
     WCAG 1.4.11 treats as graphical objects against --card-bg, and each is read
     with its own legend label beside it rather than by hue alone.

     Six is where a palette stops being distinguishable; a seventh series wraps
     rather than invents one. */
  --chart-series-1: #2563eb;
  --chart-series-2: #8b5cf6;
  --chart-series-3: #f97316;
  --chart-series-4: #14b8a6;
  --chart-series-5: #ec4899;
  --chart-series-6: #3b82f6;

  /* The REFERENCE a series is read against — 合格最低点の水準 and its like. Not
     part of the walk above: it is not another series, it is the thing the series
     is measured by, and it has to be told apart from the data at a glance rather
     than by reading a legend.

     Orange because the data is blue. It sat at --primary-light (a second blue)
     and then at --muted (a grey too faint to find), and both were reported as
     unreadable — this is the complement of --chart-series-1, which is as far
     from it as the wheel goes. Green and red are the two it may NOT be: a
     threshold is not a verdict, and this app never paints one (ADR-007). */
  --chart-reference: #f97316;

  /* A bar is an AREA; a line is a 2px stroke. --chart-series-1 at full strength
     reads as a series when it is a stroke and as a slab when it fills a bar, and
     a slab swallows whatever is drawn over it — which is exactly what the
     reference line is. So a bar takes this tint as its FILL and keeps
     --chart-series-1 as its edge: same series, same identity, less ink.

     #93c5fd is the prototype's own blue-300, two steps below the series colour.
     One tint, because every bar chart in the app draws a single series today; a
     multi-series bar chart needs a ramp here and there is no reason to invent
     one before the screen that asks for it exists. */
  --chart-bar-fill: #93c5fd;

  /* The 偏差値 band ramp — 科目ごとの散らばり (#191 follow-up).

     Not --chart-series-*: that palette is CATEGORICAL and says only "a different
     series". These seven say WHERE on the scale, and they diverge about 50,
     because 50 is the 偏差値's real midpoint and not an arbitrary one. Walking
     the categorical six here would paint 45〜50 pink and 50〜55 orange and tell a
     teacher nothing about which is the low end.

     The two hues are the reference the school picked for data on 2026-08-13
     (danluu.com's own chart palette): #e41a1c below 50, and above it #377eb8 —
     the `--resume` blue of that palette's 「Medium iteration paths vs. Ultra」
     figure, picked by the school on 2026-08-14. It replaces #1a365d, which was
     the same palette's `--static`: navy survives a 12% tint as a grey, and a
     teacher reading 65以上 in grey was told a good score is a dull one. Every
     value below is its hue composited over --card-bg #ffffff at a stated
     strength, so the ramp is reproducible rather than eyeballed.

     A band is a FILL with a head-count printed on it, so each is measured
     against --foreground #1e293b, which is the text that sits on it. Blue tints
     lighter than navy at the same strength, so the four steps are spread wider
     (14/32/50/70) to keep 65以上 the heaviest step on the scale — at 70% it is
     still 5.57:1, further from the 4.5 floor than the navy it replaces. */
  /* #e41a1c at 45% — 6.80:1 with --foreground. */
  --viz-band-1: #f39899;
  /* #e41a1c at 28% — 9.17:1. */
  --viz-band-2: #f7bfbf;
  /* #e41a1c at 12% — 12.09:1. */
  --viz-band-3: #fce4e4;
  /* #377eb8 at 14% — 12.33:1. */
  --viz-band-4: #e3edf5;
  /* #377eb8 at 32% — 9.75:1. */
  --viz-band-5: #bfd6e8;
  /* #377eb8 at 50% — 7.52:1. */
  --viz-band-6: #9bbedc;
  /* #377eb8 at 70% — 5.57:1, the floor this ramp stops at. */
  --viz-band-7: #73a5cd;

  /* クラスの強み・弱み's two directions. The reference the school picked for data
     on 2026-08-13 (danluu.com) rather than --success / --danger: those are the
     STATUS colours, and 「学年より上」 is a position, not a verdict. The 科目別
     table's 差 cell used the status pair for this number and is gone with the
     table, so nothing on the screen colours it the other way any more.

     Two values per direction, because the same colour does two jobs here. The
     BAR is a graphical object read with its own legend label beside it (the
     same reasoning --chart-series-* records), so it carries the reference hue.
     The number at its tip is TEXT and is held to 4.5:1 — and #38b2ac reaches
     only 2.58:1 on --card-bg, so the ink is the same hue taken darker. */
  --viz-above: #38b2ac;
  /* #38b2ac darkened until it clears the body floor — 5.14:1 on --card-bg. */
  --viz-above-ink: #1a7a75;
  /* 4.71:1 on --card-bg, so the fill and the ink can be the one value. */
  --viz-below: #e41a1c;
  --viz-below-ink: #e41a1c;

  /* The row 成績マトリクス has a カルテ open for. Translucent on purpose — it lies
     over the band fills, and an opaque mark would take the 偏差値's colour off
     the row a teacher is looking at, which is the one row they most need to
     read. The only rgba in this file, and it is here for that reason.

     Orange because nothing else on these screens is: the bands are red↔blue, the
     directions teal/red, so a warm wash cannot be read as a value. #ff7f00 at 9%
     is the reference layout's own (danluu.com palette, 2026-08-13).

     Measured over every band against --foreground, which is the text that sits
     on it: the darkest step (--viz-band-7) goes 5.57 → 5.44, and the whole ramp
     stays over 4.5. The mark is redundant anyway — the panel beside it names the
     student — so it is a confirmation, never the only way to know. */
  --viz-picked: rgba(255, 127, 0, 0.09);

  /* The 0 line of クラスの強み・弱み. The four ticks beside it are --border, this
     app's own hairline; the axis is that same neutral taken darker, because 0 is
     what every bar in the figure is measured from and a tick that happens to sit
     in the middle does not say so.

     NOT --border-strong (= --muted, 4.76:1). That is the weight WCAG 1.4.11 asks
     of a form CONTROL's boundary, and drawn down the middle of a chart it reads
     as a black bar rather than as the strongest of five gridlines. 1.4.11 is not
     what applies here: the figure prints its own scale under the bars and the
     value at each bar's tip carries its own sign, so no reader depends on seeing
     this line to know which side of 0 a 科目 is on.

     An ALIAS and not a second literal — slate-400 is the step this file already
     holds, the same way --scrollbar-thumb-hover takes it. */
  --viz-axis: var(--foreground-disabled);

  /* 設置区分 — the bar colours of 志望校の集まり. Three values from the same
     reference palette (danluu.com, picked 2026-08-13), and CATEGORICAL: 国立 and
     私立 are two kinds of school, not two ends of a scale, so this is not the
     band ramp above and must not be read as one.

     Not --chart-series-*: those six are "a different series" and carry no
     meaning of their own, whereas these three name a thing a teacher already
     knows, and 国立 has to stay the same colour on every screen that draws it.

     The three are separated by LIGHTNESS as well as hue — 12.14:1, 4.34:1 and
     2.58:1 on --card-bg — so they stay three different bars in greyscale and for
     a red-green deficiency. That matters more here than each one's own contrast
     with the card, because these bars are compared with each other. They are
     also never the ONLY carrier of the 設置区分: each bar states it in its
     accessible name, and the count beside it is --foreground text.

     設置区分 not stated on the master row is drawn as an OUTLINE rather than a
     fourth colour (home.css .home-asp__bar--unknown). A grey light enough not to
     compete with the three would sit at the same lightness as the teal, and "not
     recorded" reading as "no ink" is the honest picture anyway. */
  --viz-founding-national: #1a365d;
  --viz-founding-public: #377eb8;
  --viz-founding-private: #38b2ac;

  /* The roles the prototype expresses as Tailwind utility classes rather than as
     properties of its own. Each is named for the job it does, not for the value
     that fills it today: --border-strong is the boundary that identifies a
     control, and it only happens to equal --muted. Until #137 these lived in a
     bridge layer under --color-* names, aliasing the twelve above one-for-one;
     that layer went when its last reference did, and the names that survived are
     the ones that mean something the palette does not already say. */

  /* slate-400, 2.56:1 on --card-bg. The prototype has no disabled colour — it
     dims with disabled:opacity-50/60 — and WCAG 1.4.3 exempts inactive
     components from the contrast requirement. */
  --foreground-disabled: #94a3b8;
  --primary-foreground: #ffffff;

  /* The scrollbar thumb (tools/tailwind/src.css ::-webkit-scrollbar-thumb).
     slate-300, and its own value rather than a reuse: --border at 1.23:1 is too
     faint to aim at, and --border-strong is darker than any scrollbar on these
     screens. The hover state is an ALIAS and not a second literal — the
     prototype's two thumb greys are consecutive steps of one ramp, and the
     darker one is the grey this file already holds. */
  --scrollbar-thumb: #cbd5e1;
  --scrollbar-thumb-hover: var(--foreground-disabled);

  /* The boundary that identifies a form control needs 3:1 (WCAG 1.4.11). The
     prototype draws its own inputs with --border at 1.23:1 and slate-400 reaches
     only 2.56:1, so slate-500 is the first step over the line — darker than the
     prototype, which is the trade ADR-020 §Decision 3 already made. The retired
     Fluent --color-border-strong #a9abb2 was 2.29:1, below 3:1 as well. */
  --border-strong: var(--muted);
  /* The blue, not the ink: a navy ring on a navy button is not a ring. */
  --focus-ring: var(--blue);

  /* Status fills and borders come from the prototype's own badge classes. The
     three colours themselves are --success / --warning / --danger above. */
  --success-bg: #f1f8f6;
  --success-border: #bcd9d3;
  --warning-bg: #fff7dd;
  --warning-border: #f5dc8a;
  --danger-bg: #fdf2f2;
  --danger-border: #f2c2c2;
  /* The prototype has no info status: .highlight-info is primary on accent
     (4.75:1), and its border is the blue-200 the prototype uses elsewhere. All
     three members are kept even though two are aliases, so a screen spells the
     fourth status exactly like the other three. */
  --info: var(--link);
  --info-bg: var(--accent);
  --info-border: #c5d9ea;

  --font-family-base: "Noto Sans JP", "Hiragino Kaku Gothic ProN", "Hiragino Sans",
    "Yu Gothic UI", Meiryo, system-ui, sans-serif;
  --font-family-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
    "Noto Sans Mono", monospace;

  /* Fluent 2 type ramp. */
  --font-size-caption2: 10px;
  --line-height-caption2: 14px;
  --font-size-caption1: 12px;
  --line-height-caption1: 16px;
  --font-size-body1: 14px;
  --line-height-body1: 20px;
  --font-size-body1-strong: var(--font-size-body1);
  --line-height-body1-strong: var(--line-height-body1);
  --font-size-subtitle2: 16px;
  --line-height-subtitle2: 22px;
  --font-size-subtitle1: 20px;
  --line-height-subtitle1: 28px;
  --font-size-title3: 24px;
  --line-height-title3: 32px;
  --font-size-title2: 28px;
  --line-height-title2: 36px;
  --font-size-title1: 32px;
  --line-height-title1: 40px;
  --font-size-large-title: 40px;
  --line-height-large-title: 52px;
  --font-size-display: 68px;
  --line-height-display: 92px;

  /* Noto Sans JP ships 400 / 500 / 700 — Fluent's 600 "strong" maps to 700. */
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-strong: 700;

  /* Spacing — 4px base. */
  --space-none: 0;
  /* Half a step, and the only one below the base. It exists for data grids
     (careers' university list, #211): a reference table a teacher scans column
     against column wants Excel's row height, and 4px of vertical padding on
     12px type is already 50% taller than that. Reach for it ONLY for cell
     padding and the gaps inside a grid header — a layout that wants 2px between
     two blocks is a layout that wants --space-xs. */
  --space-xxs: 2px;
  --space-xs: 4px;
  --space-s: 8px;
  --space-m: 12px;
  --space-l: 16px;
  --space-xl: 20px;
  --space-xxl: 24px;
  --space-xxxl: 32px;
  --space-xxxxl: 48px;

  /* ONE corner for the whole app, and two named exceptions. Nothing else.

     --radius is it. Buttons, fields, cards, modals, panels, banners, tabs,
     chips, badges, avatars, dropdowns — everything that draws a box (PM,
     2026-08-10: 「テーブルデータ以外は全部同じ」). There is deliberately no
     second token holding the same number: this file used to carry --radius-card
     beside --radius-control, both meaning "the app's corner", and a second name
     for one value is the indirection #137 retired the colour bridge over. It
     also made the bug this replaces possible — the surfaces stayed at 0 while
     the controls moved to 6px, and every screen showed both.

     It supersedes #216's "every corner square". That decision was made when the
     alternative was rounded CARDS over square TABLES, which is two shape
     languages on one page; a single corner everywhere is not that.

     --radius-grid — the table's own furniture: the scroll frame, the pager, the
     page-size select, the column menu with its needle and apply button. Square,
     and separately named because that is a DECISION, not a leftover. The cells
     are square boxes so the furniture around them is too, and it must not follow
     --radius the day that number moves.

     --radius-circular — a PERCENTAGE, so it is a shape and not a size: "a circle,
     whatever this box measures". Exactly one thing on these screens genuinely is
     one — the DOT on the 出願条件との距離 band and the swatch tying each figure
     below it to that dot. A plotted point is round in every chart the app draws,
     and a squircle among them reads as a bug, which is how it was reported. A
     label, a chip or a badge naming this token is a mistake; a marker naming it
     is the point.

     No RULE writes a literal radius any more — that is what makes a change to
     any of these a one-line edit, and it is now true of tools/tailwind/src.css
     too (.card and .stat-card carried the prototype's 0.75rem until this). The
     one literal left is the scrollbar thumb's 3px, and it is not an exception
     worth naming: the thumb is 6px wide, so 3px is "half of me" rather than a
     corner anyone chose. A token would make it follow a number it must not. */
  --radius: 6px;
  --radius-grid: 0;
  --radius-circular: 50%;

  --border-width-thin: 1px;
  --border-width-thick: 2px;

  /* The prototype's control transition (`transition: background 0.15s ease`).
     A duration is neither a colour, a size, nor a radius, so the token-purity
     test would not have caught it as a literal — it lives here because the rule
     this file states is that values live here. */
  --duration-fast: 0.15s;

  /* Picking a row up and putting it down (static/js/row-reorder.js). Both are
     short enough not to be waited on and long enough to be followed by the eye.
     The easings are decelerations — fast at the start, settling at the end,
     which is what a thing with weight does. The drop's is the stronger of the
     two because a released row should look like it is finding its slot rather
     than sliding to it; the numbers are react-beautiful-dnd's drop curve, which
     is the one everybody's hands are already trained on. */
  --duration-lift: 0.16s;
  --ease-lift: cubic-bezier(0.2, 0, 0, 1);
  --duration-drop: 0.22s;
  --ease-drop: cubic-bezier(0.2, 1, 0.1, 1);

  /* The content column, header and <main> alike (.site-column). 1280px is the
     prototype's own max-w-7xl. Issue 131 dropped it for full width on the
     argument that a roster wants every pixel; #216 put it back (PM) — what full
     width produced was a card stretched across 1920px, and a table wider than
     the column has its own scroll box to live in. */
  --layout-content-max-width: 1280px;

  /* How much vertical room is NOT available to a .c-solo card (components.css) —
     what the sticky header and <main>'s own padding-block take before the card
     gets to centre itself in the rest.

     Measured, like --layout-toast-top below and for the same reason: the header
     is content-driven, so its height is not derivable from a token. It is also
     APPROXIMATE — the two header bands are 74px and .site-main pads 16px a side,
     which is 106, and this is 96. Reserving 10px too few lets the box run 10px
     past the bottom, so the card sits 5px BELOW true centre — which is why it
     has gone unnoticed since 216e73f wrote it as `--space-xxxxl` twice. Kept at
     96 rather than corrected here: moving it moves the login screen, and this
     change is meant to leave that screen exactly where it is. Re-measure both
     numbers if the header gains a band. */
  --layout-solo-reserve: 96px;

  /* Where the floating flash region starts (components/toast.html). It has to
     clear the sticky header, whose height is content-driven — two bands, 74px
     as they stand — so this is a measured number rather than a derived one.
     Getting it wrong is cosmetic in one direction only: too large just floats
     the toasts lower, while too small puts them over the account menu, which a
     warning that waits to be dismissed would then block. Re-measure it if the
     header gains or loses a band. */
  --layout-toast-top: 90px;

  /* The sticky header's own height — the two bands, measured. Two comments in
     this file already quote 「74px」 in prose; this is that number given a name,
     so a rule that has to clear the header can say so instead of guessing.
     Re-measure it with the other two if the header gains or loses a band. */
  --layout-header-height: 74px;

  /* Five elevations, and the names say which is which (issue 132). The card
     shadow is the prototype's own, copied from .card in src.css — barely there,
     because a card is on the page rather than over it. */
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.06);
  /* .stat-card's, which is --shadow-card's first layer and nothing else. It gets
     its own name rather than folding into --shadow-card because it IS a
     different value: pointing .stat-card at the two-layer shadow would deepen
     every stat card on the home screen, and that is a design change, not a
     de-duplication. Whether the prototype meant the two to differ is a question
     for the PM; until it is asked, the screens keep the shadow they have. */
  --shadow-card-flat: 0 1px 3px rgba(0, 0, 0, 0.04);
  /* .card-hover, the only card on these screens that answers the pointer: the
     same two-layer shape, deeper, and tinted rather than neutral — rgb(37 99 235)
     is --primary #2563eb, which is why a hovered card reads as leaning toward the
     cursor instead of just getting darker. Written out rather than mixed from
     var(--primary) at 10%/6%: this file's job is to hold values, and a
     color-mix() in a box-shadow would hide two of them behind arithmetic. */
  --shadow-card-hover: 0 4px 12px rgba(37, 99, 235, 0.1), 0 2px 4px rgba(37, 99, 235, 0.06);
  /* What floats over the page: menu panels, flyouts, the field-error bubble.
     Unchanged in value — it only stopped being called --shadow-card, which it
     never was. */
  --shadow-overlay: 0 1px 3px rgba(28, 29, 33, 0.08), 0 4px 16px rgba(28, 29, 33, 0.12);
  /* What is HELD, not merely floating: the row under a dragging finger. It has
     to read as picked up at a glance and against a striped table, which the
     overlay shadow does not — it is a panel shadow, and on a wide row it was
     invisible (reported 2026-08-12). The close, dark contact shadow is what says
     "off the surface"; the wide soft one gives it height. Both are darker than
     anything else here on purpose: this is the only element the pointer is
     carrying. */
  --shadow-lifted: 0 2px 4px rgba(28, 29, 33, 0.16), 0 12px 28px rgba(28, 29, 33, 0.22);
}
