/* ============================================================================
   Sessura — engagement-owned product UI system
   run: sessura_clinic_ops_uiux_20260819_z0   (claude-opus-5, frontend owner)

   Authority for this file
     tokens ......... design_kit/inputs/UIUX_DESIGN_TOKENS.json
                      + design_kit/inputs/PENPOT_DESIGN_SYSTEM_EXTRACT.json (② reviewed)
     type ........... design_kit/inputs/UIUX_TYPOGRAPHY_DECISION.json
                      every role delivery_mode=system — no webfont, no remote request
     jp mechanics ... templates/design/_golden/jp-contract/jp-typography-contract.css
                      (G36 canonical contract; COPY_DECK 描画規約 第5版 requires it)
     composition .... design_kit/visual_authoring/COMPOSITION_TRANSPLANT_PLAN.json
                      day-ledger=mobbin-09  course-rail/course-meter=mobbin-40
                      state-signals=mobbin-38  empty-day=mobbin-32
                      (mobbin-15 read only as the stat-tile shape to avoid)
     canon .......... VISUAL_DIRECTION.png, GOLDEN_SCREEN_DESKTOP.png,
                      GOLDEN_SCREEN_MOBILE.png, PENPOT_DS_01..05.png
     drawing rules .. design_kit/inputs/COPY_DECK.md §描画規約 第1〜5版

   Normalizations, taken under the run authority order (product truth and
   WCAG 2.2 AA outrank the compiled DS; DESIGN_AUTHORITY_MATRIX records
   semantic_state_colors action=normalize):

   N1  brand.color.sage is never a text colour. PRODUCT_BRIEF fixes body copy to
       ink-on-paper / paper-on-ink; sage measures 3.47:1 on paper. Sage keeps its
       graphic and surface roles (受付済 chip ground, empty-day figure stroke).
   N2  the 担当外 chip is a hairline outline chip with muted ink text, so it is
       the quietest chip in the set while still clearing AA.
   N3  no runtime colour calculation anywhere. Every semantic is a literal hex,
       so one state is one colour in light, in dark and in a still capture.
   N4  第4版: the visible focus ring is an ink contour over a paper halo — a
       luminance contrast, not the off-brand blue. --sem-focus stays declared at
       the ② reviewed value; only the ring's presentation changed.
   N5  第5版 / G36: no negative letter-spacing anywhere (it collides CJK glyph
       bodies), palt on headings and short labels only, body line-height 1.75,
       and Japanese wrapping is governed by line-break:strict + authored .nb
       chunks — never by scattered <wbr> and never by word-break overrides.

   Capture determinism: nothing on this page has its initial visibility gated by
   an entrance animation. Base styles render the settled screen; motion is an
   additive layer under prefers-reduced-motion: no-preference and is never
   `both`-filled from an invisible keyframe.
   ========================================================================== */

/* ---------------------------------------------------------------- 1. tokens */
:root {
  color-scheme: light;

  /* brand primitives — sessura_logo_oneshot_20260815_2 CANONICAL palette */
  --brand-clay:  #C4786A;
  --brand-ink:   #1B2420;
  --brand-paper: #F3EEE6;
  --brand-sage:  #6B8476;
  --brand-wine:  #6E3540;

  /* authored semantic roles — declared values, never derived from the brand */
  --sem-success:  #0B6B45;
  --sem-warning:  #8A5A00;
  --sem-blocked:  #A3241C;
  --sem-focus:    #1D5FD0;
  --sem-selected: #233029;
  --sem-track:    #E2D8C7;

  /* theme fingerprint (THEME_ACTIVATION_CONTRACT.fingerprint_css_variables) */
  --canvas:  #E9E2D6;
  --surface: #F3EEE6;
  --text:    #1B2420;
  --line:    #DBD1C0;
  --accent:  #C4786A;

  /* theme-resolved derivatives */
  --surface-2:  #EBE5D9;
  --text-muted: #55605B;   /* 5.08:1 on --canvas, 5.72:1 on --surface */
  --hairline:   #CFC4B1;

  /* the selected / 本日 unit is always the inverse of the canvas */
  --invert-surface: #233029;
  --invert-text:    #F3EEE6;
  --invert-muted:   #C3CCC7;
  /* the addressed state of that same unit — a ground lift, not a new hue, so a
     still interaction frame carries the feedback even at review scale */
  --invert-surface-hover: #33453B;

  /* focus (N4) */
  --focus-contour: #1B2420;
  --focus-halo:    #F3EEE6;

  /* pinned meter vocabulary — NOT redeclared per theme, so one segment keeps
     one hue on every surface and in both themes (実施済 / 本日の枠 / 残) */
  --meter-done:  #C4786A;
  --meter-today: #233029;
  --meter-rest:  #E2D8C7;
  --meter-ink:   #1B2420;
  --meter-paper: #F3EEE6;

  /* chip grounds — fixed in both themes (N3) */
  --chip-accept-bg: #DCE3DC;
  --chip-accept-bd: #B3C2B7;
  --chip-accept-fg: #24302A;

  /* spacing — the ② reviewed five-step scale.
     --space-2xl is a build-scoped extension used only for page/empty rhythm */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 24px;
  --space-2xl: 40px;

  /* radius */
  --radius-chip: 999px;
  --radius-card: 8px;
  --radius-control: 6px;

  /* families — UIUX_TYPOGRAPHY_DECISION, jp_heading_face=direction_owned.
     A named Japanese family always precedes the generic keyword (G36). */
  --font-display: "Avenir Next", "Futura", "Century Gothic", "Hiragino Kaku Gothic ProN", "Hiragino Sans", system-ui, sans-serif;
  --font-heading: "Avenir Next", "Futura", "Century Gothic", "Hiragino Kaku Gothic ProN", "Hiragino Sans", system-ui, sans-serif;
  --font-body:    "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Yu Gothic Medium", "Noto Sans JP", system-ui, sans-serif;
  --font-ui:      "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Yu Gothic Medium", "Noto Sans JP", system-ui, sans-serif;
  --font-mono:    Menlo, "SF Mono", ui-monospace, "JetBrains Mono", monospace;

  /* the sticky shell's own height, used for scroll-margin and rail offset */
  --shell-h: 60px;
  --page-max: 1360px;

  /* the ledger's column rhythm — one declaration drives the header strip and
     every row, so a heading can never drift off its column (mobbin-09).
     §17 re-allocates this at ≥1320px, where the pane is wide enough that the
     identity column would otherwise carry a horizontal void. */
  --ledger-cols: 56px minmax(0, 1fr) 92px 84px 104px 20px;
  --ledger-gap: var(--space-lg);
}

html[data-theme="dark"] {
  color-scheme: dark;

  --canvas:  #141A17;
  --surface: #1B2420;
  --text:    #F3EEE6;
  --line:    #2E3A34;
  --accent:  #C4786A;

  --surface-2:  #222C27;
  --text-muted: #B4BEB9;   /* 8.0:1 on --surface */
  --hairline:   #3A4640;

  --invert-surface: #F3EEE6;
  --invert-text:    #1B2420;
  --invert-muted:   #4B5652;
  --invert-surface-hover: #FBF7F0;

  --focus-contour: #F3EEE6;
  --focus-halo:    #1B2420;
}

/* ------------------------------------------- 2. Japanese text environment --
   COPY_DECK 描画規約 第5版 binds this build to the repository's canonical JP
   typography contract (templates/design/_golden/jp-contract/, G36). The rules
   below reproduce it token-equivalently for this engagement's own families.  */
html:lang(ja) {
  line-break: strict;          /* kinsoku — no orphaned punctuation           */
  word-break: normal;          /* never break-all: it wrecks JP prose         */
  overflow-wrap: anywhere;     /* long Latin tokens may still wrap            */
  font-kerning: auto;
  font-feature-settings: normal; /* NO body-wide palt (G36 FAIL if body-wide) */
  text-autospace: normal;
}

:lang(ja) p,
:lang(ja) li,
:lang(ja) dd {
  line-height: 1.75;
  letter-spacing: 0;           /* 0 to 0.02em; negative is a G36 FAIL          */
  line-break: strict;
  word-break: normal;
  overflow-wrap: anywhere;
}

:lang(ja) h1,
:lang(ja) h2,
:lang(ja) h3,
:lang(ja) h4 {
  line-break: strict;
  word-break: normal;
  overflow-wrap: anywhere;
  font-kerning: auto;
}

:lang(ja) h1,
:lang(ja) h2,
:lang(ja) h3 {
  word-break: auto-phrase;
  text-wrap: pretty;
}

:lang(ja) h1 { line-height: 1.35; letter-spacing: 0; }
:lang(ja) h2 { line-height: 1.40; letter-spacing: 0; }
:lang(ja) h3 { line-height: 1.45; letter-spacing: 0; }

/* palt — headings and short labels only */
:lang(ja) :where(h1, h2, h3, .label, .eyebrow, .badge) { font-feature-settings: "palt"; }

:lang(ja) button { line-break: strict; word-break: normal; }

/* -------------------------------------------------------------- 3. baseline */
*, *::before, *::after { box-sizing: border-box; }

/* D8 — html/body height is content-driven. `height: 100%` would cap the sticky
   topbar's containing block at one viewport and unstick it on first scroll. */
body {
  margin: 0;
  min-height: 100vh;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  text-wrap: pretty;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 600;
  margin: 0;
}
p  { margin: 0; line-height: 1.75; }
ul, ol { margin: 0; padding: 0; list-style: none; }
dl, dt, dd { margin: 0; }
a  { color: inherit; text-decoration: none; }

[hidden] { display: none !important; }

/* N4 / D1 — a visible ring is drawn only on operable elements reached by
   keyboard. Region containers that take programmatic focus draw nothing. */
:where(a, button, [role="button"]):focus-visible {
  outline: 2px solid var(--focus-contour);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--focus-halo);
  border-radius: var(--radius-control);
}
[data-focus-region]:focus { outline: none; }
[data-focus-region] { scroll-margin-top: calc(var(--shell-h) + var(--space-lg)); }

.u-vh {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip {
  position: absolute;
  left: var(--space-lg);
  top: -64px;
  z-index: 60;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  padding: 10px var(--space-lg);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  transition: top 120ms ease;
}
.skip:focus { top: var(--space-sm); }

/* 第5版 — Japanese wrapping is bound by authored chunks. .nb is the only
   wrapping instrument in this build: a quantity and its counter, a proper
   noun, a clock time or a whole clause is one unit and cannot split. Two
   adjacent .nb units are a legal break opportunity, so a label such as
   「カウンセリング待ち」 breaks at its own meaning boundary and nowhere else —
   without a single <wbr> and without a word-break override. */
.nb { white-space: nowrap; }

.num {
  font-family: var(--font-display);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;              /* N5 — never negative */
}
.code {
  font-family: var(--font-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  white-space: nowrap;
}

/* a hairline rule separates enumerated attributes. 第5版: a text separator
   (中黒) may be stranded alone at a line end; a drawn rule belongs to the
   layout and carries no reading weight when it lands there. */
.sep {
  display: inline-block;
  width: 1px;
  height: 11px;
  background: var(--hairline);
  vertical-align: -1px;
  flex: none;
}

.icon {
  width: 16px; height: 16px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon--sm { width: 13px; height: 13px; stroke-width: 2; }
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ------------------------------------------------------------ 4. app shell */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.topbar__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--space-xl);
  min-height: var(--shell-h);
  display: flex;
  align-items: center;
  gap: var(--space-xl);
}

/* D2 / D3 / D13 — the lockup lives in the app shell and the footer only, and
   the surface carrying it is the rendered 3:1 image box itself: no plate, no
   reserved width, exactly one mark per theme. */
.brand { display: flex; align-items: center; flex: none; order: 1; }
.brand img { display: block; width: 132px; height: 44px; }
html[data-theme="dark"] .brand .is-light { display: none; }
html:not([data-theme="dark"]) .brand .is-dark { display: none; }

.nav { order: 2; display: flex; align-items: stretch; gap: var(--space-lg); min-height: var(--shell-h); }
.nav__tab {
  position: relative;
  appearance: none;
  border: 0;
  background: none;
  padding: 0 var(--space-md);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 400;
  color: var(--text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  transition: color 120ms ease, background-color 120ms ease;
}
/* :focus is styled alongside :focus-visible because the capture driver hovers
   with a real pointer and then calls focus() programmatically — a
   :focus-visible-only treatment can leave an interaction frame with no
   observable change at all. */
.nav__tab:hover, .nav__tab:focus, .nav__tab:focus-visible { color: var(--text); background: var(--surface-2); }
/* the tab's ring is drawn INSIDE its own box, so it clears the header's bottom
   rule and the clay active underline instead of colliding with them */
.nav__tab:focus, .nav__tab:focus-visible {
  outline: 2px solid var(--focus-contour);
  outline-offset: -5px;
  box-shadow: none;
  border-radius: var(--radius-control);
}
.nav__tab[aria-current="page"] { color: var(--text); font-weight: 600; }
.nav__tab[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 3px;
  border-radius: var(--radius-chip);
  background: var(--accent);
  transition: height 120ms ease;
}
/* the active tab still has somewhere to go on hover/focus: the clay rule
   thickens, so even the already-current tab evidences feedback in a still frame */
.nav__tab[aria-current="page"]:hover::after,
.nav__tab[aria-current="page"]:focus::after,
.nav__tab[aria-current="page"]:focus-visible::after { height: 5px; }

.topbar__meta {
  order: 3;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  color: var(--text-muted);
  font-size: 12px;
}
.topbar__date { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.topbar__clinic {
  padding-left: var(--space-lg);
  border-left: 1px solid var(--line);
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
}
.theme-toggle {
  appearance: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-chip);
  padding: 6px 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-ui);
  font-size: 11.5px;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.theme-toggle:hover, .theme-toggle:focus, .theme-toggle:focus-visible {
  color: var(--text); background: var(--surface-2); border-color: var(--hairline);
}

.page {
  flex: 1;
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-xl) var(--space-xl) var(--space-2xl);
}

/* ------------------------------------------------------------ 5. kpi band - */
/* mobbin-15 is studied here as the shape to avoid: no four large stat tiles.
   One dense line of number/label pairs, hairline-divided, ruled top and bottom
   (GOLDEN_SCREEN_DESKTOP / GOLDEN_SCREEN_MOBILE — the band never becomes tiles). */
.kpi {
  display: flex;
  align-items: stretch;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-xl);
}
.kpi__stat {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--space-md) var(--space-lg) var(--space-md) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}
.kpi__stat + .kpi__stat { padding-left: var(--space-lg); border-left: 1px solid var(--line); }
.kpi__value { font-size: 30px; line-height: 1.05; }
.kpi__label {
  font-family: var(--font-ui);
  font-size: 11px;
  color: var(--text-muted);
  letter-spacing: 0.02em;
  line-height: 1.45;
}
.kpi__scope {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--text-muted);
  margin-top: 2px;
}
.kpi__scope .code { font-size: 11px; }

/* ------------------------------------------------ 6. state-signal legend -- */
/* D5 — this is a stated breakdown, not a filter. No hover, no pressed and no
   selected treatment, because this product has no state filter. */
.signals {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md) var(--space-lg);
  padding: 0 0 var(--space-lg);
}
.signals__label {
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  padding-right: var(--space-sm);
  border-right: 1px solid var(--line);
}
.signals__item {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 12px;
  color: var(--text-muted);
}
.signals__item .chip { transform: translateY(1px); }
.signals__n {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- 7. board layout -- */
.board {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--space-xl);
  align-items: start;
}
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
}
.panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-lg) var(--space-md);
}
.panel__title { font-size: 14px; font-weight: 600; }
.panel__note { font-size: 11px; color: var(--text-muted); }
.panel__foot {
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.75;
}

/* --------------------------------------------------------- 8. day ledger -- */
/* mobbin-09 anatomy: a headed, continuous appointment table — the reference's
   own column strip (Ref # / Service / … / Status) is part of what makes it
   readable at width, so the columns are named here too. A time anchor is
   pinned to the left edge, identity is inline, 担当 and 施術室 are their own
   quiet columns and the state chip closes the row at the right. No card seams,
   so the time rhythm is unbroken; only the selected row takes a surface.
   第3版 #11 — the row-end arrow appears on every row that owns a course
   document and on no other, independent of state and of selection. */
.ledger { padding: 0 var(--space-sm) var(--space-sm); }

.ledger__head {
  display: grid;
  grid-template-columns: var(--ledger-cols);
  gap: var(--ledger-gap);
  align-items: center;
  margin: 0 var(--space-sm);
  padding: 0 var(--space-md) var(--space-sm);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-ui);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  white-space: nowrap;
}
.ledger__head span:nth-child(5) { text-align: right; }

.row {
  position: relative;
  width: 100%;
  display: grid;
  grid-template-columns: var(--ledger-cols);
  align-items: center;
  gap: var(--ledger-gap);
  padding: var(--space-md);
  border-radius: var(--radius-card);
  color: inherit;
  text-align: left;
}
.ledger li + li .row::before {
  content: "";
  position: absolute;
  left: var(--space-md); right: var(--space-md); top: -0.5px;
  height: 1px;
  background: var(--line);
}
/* the selected row's own ground is the separation; a hairline above or below it
   would only cut into that block. The empty <li> between them is the inline
   rail slot, which is why both offsets are covered. */
.ledger li:has(.row--selected) .row::before,
.ledger li:has(.row--selected) + li .row::before,
.ledger li:has(.row--selected) + li + li .row::before { background: transparent; }

.row--open { cursor: pointer; transition: background-color 120ms ease; }
.row--open:hover, .row--open:focus, .row--open:focus-visible { background: var(--surface-2); }
.row--open:hover::before { background: transparent; }
.row--open:active { transform: translateY(1px); }
/* the row's ring is drawn inside its own rounded box so it reads as the row
   being addressed rather than as a rectangle laid over the ledger.
   証跡被覆 — plain :focus is styled alongside :focus-visible because the capture
   driver hovers with a real pointer and then calls focus() programmatically; a
   :focus-visible-only ring can leave an interaction frame with no evidence. */
.row--open:focus, .row--open:focus-visible {
  outline: 2px solid var(--focus-contour);
  outline-offset: -2px;
  box-shadow: none;
  border-radius: var(--radius-card);
}

.row__time {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
.row__main { min-width: 0; display: flex; flex-direction: column; gap: var(--space-xs); }
.row__treatment { font-family: var(--font-ui); font-size: 14px; font-weight: 600; line-height: 1.45; }
.row__meta {
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.55;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-wrap: wrap;
}
/* the auxiliary pair is a passthrough on the wide composition so 担当 and
   施術室 sit in their own named columns, and a real flex line on the phone */
.row__aux { display: contents; }
.row__staff, .row__room {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  min-width: 0;
}
.row__room { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* D4 — an unknown value is stated, never a bare dash */
.row__room--unset { font-family: var(--font-ui); font-size: 11px; }
/* 担当外: 担当 and 施術室 are one withheld cell rather than two repeated ones */
.row__withheld {
  grid-column: span 2;
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-ui);
  font-size: 11px;
  color: var(--text-muted);
}
.row__chip { display: flex; justify-content: flex-end; }
.row__go { display: flex; justify-content: flex-end; color: var(--text-muted); }
.row__go .icon { transition: transform 120ms ease; }
.row--open:hover .row__go .icon,
.row--open:focus .row__go .icon,
.row--open:focus-visible .row__go .icon { transform: translateX(3px); }
.row--open:active .row__go .icon { transform: translateX(5px); }

/* 担当外: the record keeps its place in the time rhythm; the identity is not
   shown at all, and the row states why rather than going blank */
.row--muted .row__treatment { color: var(--text-muted); font-weight: 500; }

/* the one surface inside the ledger, with the clay edge (GOLDEN_SCREEN) */
.row--selected {
  background: var(--invert-surface);
  color: var(--invert-text);
  overflow: hidden;
}
.row--selected:hover, .row--selected:focus, .row--selected:focus-visible { background: var(--invert-surface); }
.row--selected::after {
  content: "";
  position: absolute;
  left: 0; top: 4px; bottom: 4px;
  width: 4px;
  background: var(--accent);
  transition: width 120ms ease, top 120ms ease, bottom 120ms ease;
}
/* the designated primary row's ground is already the strongest on the screen,
   so the clay edge is what answers instead: it widens and runs the full row
   height on hover/focus and the row-end arrow travels with it — a change a
   still frame can carry. */
.row--selected:hover::after,
.row--selected:focus::after,
.row--selected:focus-visible::after { width: 6px; top: 0; bottom: 0; }
.row--selected .row__time,
.row--selected .row__meta,
.row--selected .row__staff,
.row--selected .row__room,
.row--selected .row__go { color: var(--invert-muted); }
.row--selected .sep { background: var(--invert-muted); }
.row--selected + .row::before,
.row--selected::before { background: transparent; }
/* the inset ring inverts on the selected row's ink ground, or it would be an
   ink contour drawn on ink — matched on plain :focus for the same reason the
   row's other addressed treatments are */
.row--selected:focus, .row--selected:focus-visible { outline-color: var(--invert-text); }

/* ------------------------------------------------------------- 9. chips --- */
/* PENPOT_DS_05 状態チップ inventory */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: var(--radius-chip);
  border: 1px solid transparent;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.45;
  white-space: nowrap;
  color: var(--brand-paper);
}
.chip--accepted { background: var(--chip-accept-bg); border-color: var(--chip-accept-bd); color: var(--chip-accept-fg); }
.chip--recorded { background: var(--sem-success); }
.chip--open     { background: var(--sem-warning); }
.chip--blocked  { background: var(--sem-blocked); }
/* N2 — the quietest chip in the set, still clearing AA */
.chip--out { background: transparent; border-color: var(--hairline); color: var(--text-muted); font-weight: 400; }
.row--selected .chip--out { border-color: var(--invert-muted); color: var(--invert-muted); }

/* ---------------------------------------------------------- 10. buttons --- */
/* ② 決定3 — the surface itself is the container and the label is its child;
   never a background rectangle with a sibling text node.
   第4版 #1 — the strongest ground on a screen belongs to the one action about
   to be performed. Back links, completed statements and demo controls are
   outline or pale surfaces. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  min-height: 44px;
  padding: 0 var(--space-lg);
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  cursor: pointer;
  background: none;
  color: inherit;
  transition: background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}
.btn--primary { background: var(--invert-surface); color: var(--invert-text); }
/* 第9サイクル指摘 — a 2px ring alone was not perceptible at review scale on the
   empty board's 通常の予定に戻す. The addressed state now lifts the control's own
   GROUND as well, and the ring is drawn at the accepted 2px offset (a paper
   halo then a clay contour), so the change reads in a still frame at 390px. */
.btn--primary:hover, .btn--primary:focus, .btn--primary:focus-visible {
  background: var(--invert-surface-hover);
  box-shadow: 0 0 0 2px var(--focus-halo), 0 0 0 4px var(--accent);
}
.btn--primary:active { transform: translateY(1px); }
.btn--primary .icon { transition: transform 120ms ease; }
.btn--primary:hover .icon, .btn--primary:focus .icon { transform: translateX(2px); }
.btn--quiet { background: var(--surface); border-color: var(--line); color: var(--text); }
.btn--quiet:hover, .btn--quiet:focus, .btn--quiet:focus-visible { background: var(--surface-2); border-color: var(--hairline); }
.btn--quiet:active { transform: translateY(1px); }

/* 第4版 #1 — the back affordance is an outline surface, never the record CTA's
   peer in weight, and it keeps the button anatomy (② 決定3). */
.btn--back {
  background: transparent;
  border-color: var(--hairline);
  color: var(--text);
  min-height: 38px;
  font-size: 12.5px;
}
/* 証跡被覆 — 本日のボードへ戻る is one of the two controls the recorded state can
   evidence, so its addressed state carries a ground shift, an ink contour at the
   accepted 2px offset and a travelling icon, not a ground shift alone. */
.btn--back:hover, .btn--back:focus, .btn--back:focus-visible {
  background: var(--surface-2);
  border-color: var(--focus-contour);
  box-shadow: 0 0 0 2px var(--focus-halo), 0 0 0 4px var(--focus-contour);
}
.btn--back .icon { transition: transform 120ms ease; }
.btn--back:hover .icon, .btn--back:focus .icon, .btn--back:focus-visible .icon { transform: translateX(-3px); }

/* D6 / 第4版 #2 — the completed task retires the imperative. 記録済み keeps the
   control's place and anatomy but states completion: a pale ground with the
   success contour and a check. It is never drawn as a solid button. */
.btn--done {
  background: var(--surface-2);
  border-color: var(--sem-success);
  color: var(--sem-success);
  cursor: default;
}
html[data-theme="dark"] .btn--done { color: #6FCFA3; border-color: #6FCFA3; }
/* 証跡被覆 — the completed statement is the other control the recorded state can
   evidence. It stays a statement (never a solid live control, 第4版 #2) but its
   addressed state is unmistakable: the success contour thickens inside and a
   success ring is drawn at the accepted 2px offset. */
.btn--done:hover, .btn--done:focus, .btn--done:focus-visible {
  background: var(--surface-2);
  box-shadow: inset 0 0 0 2px var(--sem-success), 0 0 0 2px var(--surface), 0 0 0 4px var(--sem-success);
}
html[data-theme="dark"] .btn--done:hover,
html[data-theme="dark"] .btn--done:focus,
html[data-theme="dark"] .btn--done:focus-visible {
  box-shadow: inset 0 0 0 2px #6FCFA3, 0 0 0 2px var(--surface), 0 0 0 4px #6FCFA3;
}

/* the refused control stays reachable by keyboard (aria-disabled, not
   disabled) so an operator can read WHY it cannot be pressed. On hover and on
   focus it draws a blocked-coloured dashed contour and lifts its own reason
   text to full ink — the refusal explains itself in the same frame. */
.btn--blocked {
  background: var(--surface-2);
  border-color: var(--hairline);
  border-style: dashed;
  color: var(--text-muted);
  cursor: not-allowed;
}
.btn--blocked:hover, .btn--blocked:focus, .btn--blocked:focus-visible {
  background: var(--surface-2);
  border-color: var(--sem-blocked);
  color: var(--sem-blocked);
}
html[data-theme="dark"] .btn--blocked:hover,
html[data-theme="dark"] .btn--blocked:focus,
html[data-theme="dark"] .btn--blocked:focus-visible { border-color: #E98077; color: #E98077; }
.btn--block { width: 100%; }

/* -------------------------------------------------------- 11. usage meter - */
/* The signature of this product: the sold plan is a fixed row of segments and
   the delivered history fills it. The three-value vocabulary is the ② reviewed
   declaration — 実施済 = clay, 本日の枠 = the inverse unit, 残 = track — and the
   hues are pinned once, so a segment never changes colour between surfaces. */
.meter { display: flex; align-items: stretch; gap: var(--space-xs); }
.meter__seg { flex: 1 1 0; border-radius: var(--radius-chip); background: var(--meter-rest); }
.meter__seg--done  { background: var(--meter-done); }
/* the 本日の枠 unit carries a clay inset ring so it stays legible on the ink
   ground of the selected row — a surface treatment, not a second hue */
.meter__seg--today { background: var(--meter-today); box-shadow: inset 0 0 0 2px var(--meter-done); }

.meter--sm .meter__seg { height: 10px; }

.meter--lg { gap: 6px; }
.meter--lg .meter__seg {
  height: 52px;
  border-radius: var(--radius-card);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--meter-ink);
  transition: background-color 320ms ease, box-shadow 320ms ease, color 320ms ease;
}
.meter--lg .meter__seg--today { color: var(--meter-paper); }
.meter--lg .meter__seg--void {
  background: transparent;
  border: 1px dashed var(--hairline);
  color: var(--text-muted);
  box-shadow: none;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-lg);
  margin-top: var(--space-md);
  font-size: 11.5px;
  color: var(--text-muted);
}
/* one legend marker for every state: the same 14x8 pill, aligned to the optical
   centre of the FIRST text line so a key whose text wraps to two lines keeps its
   swatch beside the first line instead of floating to the block's centre */
.legend__key { display: inline-flex; align-items: flex-start; gap: 6px; }
.legend__swatch {
  width: 14px;
  height: 8px;
  margin-top: 6px;
  border-radius: var(--radius-chip);
  background: var(--meter-rest);
  border: 1px solid transparent;
  flex: none;
}
.legend__swatch--done  { background: var(--meter-done); }
.legend__swatch--today { background: var(--meter-today); box-shadow: inset 0 0 0 2px var(--meter-done); }
.legend__swatch--void  { background: transparent; border-color: var(--hairline); }

/* -------------------------------------------------------- 12. course rail - */
/* mobbin-40 anatomy re-anchored by ② 決定1: identity (name + course id + usage
   meter) is one block; the 実施済 / 残回数 pair and the CTA sit outside it.
   ② 決定2: the rail's block rhythm is space.md and is never compressed. */
.rail {
  position: sticky;
  top: calc(var(--shell-h) + var(--space-xl));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.rail__eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.rail__identity {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding-bottom: var(--space-md);
  border-bottom: 1px solid var(--line);
}
.rail__name { font-family: var(--font-heading); font-size: 17px; font-weight: 600; line-height: 1.45; letter-spacing: 0; }
.rail__course { font-size: 11.5px; color: var(--text-muted); display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm); }
.rail__course .code { font-size: 11.5px; }

/* 第3版 #12 — label left, value right, across the full card width, so two
   adjacent figures can never read as one number sequence at 390px. */
.pair {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-xl);
  font-size: 12px;
}
.pair__label { color: var(--text-muted); }
.pair__value { font-family: var(--font-display); font-weight: 700; font-size: 16px; font-variant-numeric: tabular-nums; letter-spacing: 0; }
.pair__value .u-of { font-size: 12px; font-weight: 600; color: var(--text-muted); }
.rail__slot { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }

/* ---------------------------------------------------- 13. state banners --- */
/* mobbin-38, corrected: the fact sentence is a persistent band inside the
   document — not a toast that leaves — and the row label of the same 回 changes
   on the same screen. ② 決定2: headline and fact block are separated by
   space.sm, never xs.
   第5版 — the band's facts are DISCRETE LABELLED ITEMS, not a 中黒-joined run.
   A dot-joined enumeration can strand its separator at a line end; a labelled
   pair cannot, because every unit carries its own label and value. */
.banner {
  display: flex;
  gap: var(--space-md);
  padding: var(--space-lg);
  border-radius: var(--radius-card);
  color: var(--brand-paper);
  margin-bottom: var(--space-lg);
}
.banner .icon { margin-top: 3px; }
.banner__body { display: flex; flex-direction: column; gap: var(--space-sm); min-width: 0; }
/* 第9サイクル指摘 — the blocking reason is the one line that must read first, and
   it was splitting 「記録でき」/「ません」. The headline is a heading-role block, so it
   takes the JP contract's heading wrapping (phrase-aware) rather than the body
   default, and the verb phrase is additionally bound as one .nb unit in markup
   so the break point does not depend on auto-phrase being available. */
.banner__headline {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.55;
  line-break: strict;
  word-break: auto-phrase;
  text-wrap: pretty;
}
.banner__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-lg);
  font-size: 12px;
  line-height: 1.6;
}
.banner__fact { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* 5.03:1 on the success ground, 5.71:1 on the blocked ground — a label on a
   solid semantic surface still clears AA for normal text */
.banner__fact dt { font-size: 10.5px; letter-spacing: 0.06em; color: #E6E1D8; white-space: nowrap; }
.banner__fact dd { color: var(--brand-paper); white-space: nowrap; font-weight: 500; line-height: 1.5; }
.banner__fact dd .num { font-size: 13px; }
.banner--recorded { background: var(--sem-success); }
.banner--blocked  { background: var(--sem-blocked); }
.banner:focus { outline: none; }

/* motion role: spatial continuity. Not `both`-filled, and only under
   no-preference, so the settled banner IS the base style and a capture taken
   with animations disabled reads as the finished screen. */
@media (prefers-reduced-motion: no-preference) {
  .banner--enter { animation: banner-in 220ms ease-out; }
}
@keyframes banner-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

/* D7 — a refusal is not a dead end: the step that clears it is on the same
   screen, carrying the DOMAIN_TRUTH_CONTRACT string verbatim. */
.recovery {
  display: flex;
  gap: var(--space-sm);
  align-items: flex-start;
  flex-wrap: wrap;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--sem-blocked);
  border-radius: var(--radius-control);
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--text);
}
.recovery__label { font-weight: 600; font-family: var(--font-ui); white-space: nowrap; }

/* the document's status line — state-signals is a visible region in every
   document state, not only after the record lands. 第5版: it is a labelled
   row, not a sentence, so nothing here can orphan a copula at a line head. */
.statusline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
  padding: var(--space-md) var(--space-lg);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-control);
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.75;
}
.statusline__label {
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  padding-right: var(--space-sm);
  border-right: 1px solid var(--hairline);
  white-space: nowrap;
}
.statusline__value {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  color: var(--text);
  font-weight: 600;
  font-family: var(--font-ui);
}
.statusline__note { flex-basis: 100%; font-size: 11.5px; color: var(--text-muted); }

/* ------------------------------------------------------ 14. course document */
.doc {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: var(--space-xl);
  max-width: 820px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}
.doc__nav { display: flex; }
.doc__identity { display: flex; flex-direction: column; gap: var(--space-sm); }
.doc__eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.doc__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(28px, 3.2vw, 40px);
  /* line-height and letter-spacing come from the JP contract's h1 rule
     (1.35 / 0) — G36 fails a Japanese heading below 1.2 and any negative
     tracking, so this element deliberately declares neither. */
}
.doc__course {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  font-size: 13px;
  color: var(--text-muted);
}
.doc__title {
  font-family: var(--font-heading);
  font-size: clamp(19px, 2vw, 23px);
  font-weight: 600;
  padding-bottom: var(--space-md);
  border-bottom: 1px solid var(--line);
}
.doc__meterblock { display: flex; flex-direction: column; margin-top: var(--space-md); }

.figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.figure { padding: var(--space-lg) var(--space-lg) var(--space-lg) 0; display: flex; flex-direction: column; gap: var(--space-xs); }
.figure + .figure { padding-left: var(--space-lg); border-left: 1px solid var(--line); }
.figure__label { font-size: 11px; color: var(--text-muted); letter-spacing: 0.02em; }
.figure__value { font-family: var(--font-display); font-weight: 700; font-size: 34px; line-height: 1.05; font-variant-numeric: tabular-nums; letter-spacing: 0; }
.figure__value .u-of, .figure__value .u-unit { font-size: 17px; font-weight: 600; color: var(--text-muted); }
/* D4 — a withheld value says so; it is never zero-filled */
.figure__value--withheld { font-family: var(--font-ui); font-size: 17px; font-weight: 600; color: var(--text-muted); line-height: 2.05; }

.history { display: flex; flex-direction: column; }
.history__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md); padding-bottom: var(--space-md); }
.history__title { font-family: var(--font-ui); font-size: 13px; font-weight: 600; }
.history__note { font-size: 11px; color: var(--text-muted); }
.hrow {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-lg);
  padding: var(--space-md) 0;
  border-top: 1px solid var(--line);
}
.hrow__no { font-family: var(--font-mono); font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.hrow__label { font-size: 13px; }
.hrow--today .hrow__label { font-weight: 600; }
.hrow--pending .hrow__label { color: var(--text-muted); }
.hrow__slot {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  justify-content: flex-end;
}
.hrow__slot .chip { font-family: var(--font-ui); }
.hrow__slot--unset { font-family: var(--font-ui); font-size: 11.5px; }

/* action surface — in-document, never pinned. One confirmation, no stepper. */
.action {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-lg);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--line);
}
.action__reason {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-size: 12.5px;
  color: var(--text-muted);
  max-width: 42em;
  line-height: 1.75;
  transition: color 120ms ease;
}
.action__reason .icon { margin-top: 3px; flex: none; }
/* 第5版 — one sentence per line box; a clause can never share a line with the
   head of the next sentence, so no copula is ever orphaned.
   第9サイクル指摘 — a sentence that still needs two lines must break between
   phrases, not inside 「更新します。」, so the note block wraps phrase-aware and its
   verb phrases are bound as .nb units in markup. */
.action__line { display: block; line-break: strict; word-break: auto-phrase; }
.action__reason--blocked .icon { color: var(--sem-blocked); }
.action__reason--done .icon { color: var(--sem-success); }
/* the refusal raises its own voice when the refused control is addressed */
.btn--blocked:hover ~ .action__reason--blocked,
.btn--blocked:focus ~ .action__reason--blocked,
.btn--blocked:focus-visible ~ .action__reason--blocked { color: var(--text); }

/* --------------------------------------------------------- 15. empty day -- */
/* mobbin-32: one restrained figure, one headline, one fact line, one way back.
   D9 — a single calendar-days line figure; staggered bars or dots would be
   indistinguishable from a loading skeleton and would make a settled empty
   state look unresolved. D10 — the control restores the day's data; there is no
   本日のボードへ戻る on a board the operator is already on. */
.empty {
  max-width: 520px;
  margin: var(--space-2xl) auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: var(--space-2xl) var(--space-xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  text-align: center;
}
.empty__figure { color: var(--brand-sage); margin-bottom: var(--space-xs); }
.empty__figure .icon { width: 40px; height: 40px; stroke-width: 1.25; }
.empty__headline { font-family: var(--font-ui); font-size: 15px; font-weight: 600; }
.empty__hint { font-size: 12px; color: var(--text-muted); line-height: 1.75; }
.empty .btn { margin-top: var(--space-sm); }

/* ------------------------------------------------------------ 16. footer -- */
.foot { border-top: 1px solid var(--line); background: var(--surface); }
.foot__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-lg) var(--space-xl);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md) var(--space-xl);
}
.foot__brand { flex: none; display: flex; align-items: center; }
.foot__brand img { display: block; width: 120px; height: 40px; }
html[data-theme="dark"] .foot__brand .is-light { display: none; }
html:not([data-theme="dark"]) .foot__brand .is-dark { display: none; }
.foot__note { flex: 1 1 320px; font-size: 11.5px; color: var(--text-muted); max-width: 42em; line-height: 1.75; }
.foot__ctrl {
  appearance: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-chip);
  padding: 8px 14px;
  font-family: var(--font-ui);
  font-size: 11.5px;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  flex: none;
  margin-left: auto;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
/* 証跡被覆 — 来院0件を再現 is one of the board's primary operable surfaces, so it
   answers with a ground shift and the accepted 2px-offset contour */
.foot__ctrl:hover, .foot__ctrl:focus, .foot__ctrl:focus-visible {
  color: var(--text);
  border-color: var(--focus-contour);
  background: var(--surface-2);
  box-shadow: 0 0 0 2px var(--focus-halo), 0 0 0 4px var(--focus-contour);
}

/* ------------------------------------------------- 17. responsive strategy */
/* This is a re-composition, not a shrink. The Golden Screens declare two
   distinct compositions and both are implemented from their own intent. */

/* Tablet band: the shell wraps into a brand+meta row and a nav strip. */
@media (max-width: 1100px) {
  :root { --shell-h: 100px; }
  .topbar__inner {
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-sm) var(--space-lg);
    padding: var(--space-sm) var(--space-lg) 0;
    min-height: 0;
  }
  .brand { order: 1; }
  .topbar__meta { order: 2; margin-left: auto; }
  .nav { order: 3; width: 100%; min-height: 44px; border-top: 1px solid var(--line); gap: var(--space-md); }
}

/* The two-pane board is a desktop composition only. Below 1081px the ledger
   takes the full width and the rail unsticks — at EVERY narrower viewport, the
   phone included. The reset stays unbounded at the low end. */
@media (max-width: 1080px) {
  .board { grid-template-columns: minmax(0, 1fr); }
  .rail { position: static; }
  /* the ledger's own column rhythm tightens rather than being abandoned, so
     the header strip still names the same columns at tablet width */
  :root { --ledger-cols: 52px minmax(0, 1fr) 76px 72px 100px 20px; --ledger-gap: var(--space-md); }
}

/* Tablet (721–1080): the rail is inline directly beneath the selected row —
   the same placement the mobile Golden Screen declares — so selecting a slot
   always produces a response inside the viewport instead of ~900px below it.
   Its children re-lay as a wide two-column block: identity left of a rule, the
   pair / slot / CTA right of it, so ② 決定1's separation survives. */
@media (min-width: 721px) and (max-width: 1080px) {
  .rail--inline {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(240px, 1fr);
    column-gap: var(--space-xl);
    row-gap: var(--space-md);
    align-items: start;
    margin: var(--space-sm) var(--space-md) var(--space-md);
  }
  .rail--inline .rail__eyebrow { grid-column: 1 / -1; }
  .rail--inline .rail__identity {
    grid-column: 1;
    grid-row: 2 / span 4;
    border-bottom: 0;
    padding-bottom: 0;
    padding-right: var(--space-xl);
    border-right: 1px solid var(--line);
  }
  .rail--inline > .pair,
  .rail--inline .rail__slot,
  .rail--inline > .btn { grid-column: 2; }
}

/* Mobile (≤720): the KPI band stays one dense four-stat line instead of
   becoming tiles, ledger rows compress to time + treatment + chip on the first
   line with 担当 / 施術室 below, and the same rail node is injected inline
   directly beneath the selected 15:00 row (GOLDEN_SCREEN_MOBILE). */
@media (max-width: 720px) {
  :root { --shell-h: 92px; }

  /* 第8サイクル指摘 — the shell is two rows, never three: the lockup shares
     its row with a right-aligned two-line date/clinic stack and the theme
     control, and the nav strip is the only other row. */
  .topbar__inner { padding: var(--space-sm) var(--space-md) 0; gap: var(--space-sm) var(--space-md); }
  .brand img { width: 120px; height: 40px; }   /* the asset's declared minimum */
  .topbar__meta {
    display: grid;
    grid-template-columns: auto auto;
    align-items: center;
    column-gap: var(--space-sm);
    row-gap: 0;
    font-size: 10.5px;
    line-height: 1.45;
  }
  .topbar__date   { grid-column: 1; grid-row: 1; justify-content: flex-end; gap: 4px; }
  .topbar__clinic { grid-column: 1; grid-row: 2; text-align: right; border-left: 0; padding-left: 0; font-size: 10.5px; }
  .theme-toggle   { grid-column: 2; grid-row: 1 / span 2; padding: 6px 10px; font-size: 10.5px; }
  .nav { min-height: 42px; gap: var(--space-sm); }
  .nav__tab { font-size: 12.5px; padding: 0 var(--space-sm); }

  .page { padding: var(--space-lg) var(--space-lg) var(--space-xl); }

  .kpi__stat { padding: var(--space-sm) var(--space-sm) var(--space-sm) 0; }
  .kpi__stat + .kpi__stat { padding-left: var(--space-sm); }
  .kpi__value { font-size: 21px; }
  /* 第9サイクル指摘 — 「カウンセリング待ち」 is the only label that wraps at 390px, so
     its tile grew one line taller and dropped its 担当分 sub-row ~14px below the
     other three. The label row reserves both lines on every tile, which puts the
     four sub-rows back on one baseline in ready AND in empty from one rule. */
  .kpi__label { font-size: 10px; letter-spacing: 0; min-height: calc(1.45em * 2); }
  .kpi__scope { font-size: 10px; gap: 3px; }
  .kpi__scope .icon--sm { width: 11px; height: 11px; }

  .signals { gap: var(--space-sm) var(--space-md); padding-bottom: var(--space-md); }

  .panel__head { flex-wrap: wrap; padding: var(--space-lg) var(--space-md) var(--space-sm); }
  .panel__note { white-space: nowrap; }
  .panel__foot { padding: var(--space-md) var(--space-md) var(--space-lg); }
  /* the ledger runs edge to edge inside the card so the selected row reads as a
     full-width band, as GOLDEN_SCREEN_MOBILE draws it */
  .ledger { padding: 0 0 var(--space-sm); }
  /* the named column strip is a wide-composition device; the phone row states
     each value with its own vocabulary instead */
  .ledger__head { display: none; }

  /* the queue row stacks instead of keeping the wide column template:
     time + treatment + state chip on the first line, patient / course id
     beneath it, 担当 and 施術室 on a third line, full width
     (GOLDEN_SCREEN_MOBILE). */
  .row {
    grid-template-columns: 48px minmax(0, 1fr) auto;
    grid-template-areas:
      "time main chip"
      "time aux  go";
    gap: var(--space-sm) var(--space-md);
    padding: var(--space-md);
  }
  .row__time { grid-area: time; align-self: start; padding-top: 2px; }
  .row__main { grid-area: main; }
  .row__chip { grid-area: chip; align-self: start; }
  .row__go   { grid-area: go; }
  .row__aux  {
    grid-area: aux;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-md);
    font-size: 11.5px;
  }
  .row__staff, .row__room { font-size: 11.5px; }
  .row__withheld { grid-column: auto; }
  .ledger li + li .row::before { left: var(--space-md); right: var(--space-md); }

  /* the inline rail is a full-width card under the selected row, never a
     column remnant */
  .rail--inline { margin: var(--space-sm) var(--space-md) var(--space-md); }

  .doc { padding: var(--space-lg); gap: var(--space-lg); }

  /* 第3版 #12 — the figures become full-width rows, label left value right */
  .figures { grid-template-columns: minmax(0, 1fr); }
  .figure {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-xl);
    padding: var(--space-md) 0;
  }
  .figure + .figure { padding-left: 0; border-left: 0; border-top: 1px solid var(--line); }
  .figure__label { font-size: 12px; }
  .figure__value { font-size: 26px; }
  .figure__value .u-of, .figure__value .u-unit { font-size: 14px; }
  .figure__value--withheld { font-size: 14px; line-height: 1.7; }

  .meter--lg { gap: 4px; }
  .meter--lg .meter__seg { height: 44px; font-size: 13px; }

  .hrow { grid-template-columns: 48px minmax(0, 1fr) auto; gap: var(--space-md); }

  .action { flex-direction: column; align-items: stretch; }
  .action .btn { width: 100%; }
  .action__reason { max-width: none; }

  .banner__facts { gap: var(--space-sm) var(--space-md); }

  /* the empty day stays a small centred block that reads without scrolling */
  .empty { margin: var(--space-xl) auto; padding: var(--space-xl) var(--space-lg); }

  /* 第4版 #4 — the footer band stays tight and sits flush at the end of the
     page; the demo pill lives inside the band, not below it */
  .foot__inner { padding: var(--space-lg); gap: var(--space-md); }
  .foot__note { flex-basis: 100%; }
  .foot__ctrl { margin-left: 0; }
}

/* very narrow — the KPI band drops its scoped sub-figure rather than wrapping */
@media (max-width: 380px) {
  .kpi__scope { display: none; }
}

/* Wide desktop (≥1320) — 第9サイクル指摘: at 1440 the ledger card was stretched to
   948px while each row carries roughly 123px of Japanese text, so the identity
   column ended at x≈280 and 担当 did not begin until x≈645 — a ~360px void on
   every row of a board that is scanned all day. The surplus is re-allocated
   rather than removed: the inspector takes 100px more (its lower half was
   measurably empty) and the auxiliary columns widen, which brings the void to
   ~219px — the balance the tablet composition was measured at and praised for.
   Both panes still span exactly the KPI band's measure, so nothing above or
   below shifts, and the threshold keeps the proven 340px composition at the
   intermediate widths where a wider rail would squeeze the ledger instead. */
@media (min-width: 1320px) {
  :root { --ledger-cols: 60px minmax(0, 1fr) 104px 96px 116px 24px; }
  .board { grid-template-columns: minmax(0, 1fr) 440px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .row--open:active, .btn--primary:active, .btn--quiet:active { transform: none; }
}
