/* Kanban comfort features shared by both portals (see board.js). */

/* View settings bar (D-05, user request 2026-09-29): three labelled groups in one visual language -
   카드 [모두 펴기|모두 접기], 정렬 [select], 단계 [빈 단계 접기|모두 접기|모두 펴기]. A segmented control is one framed
   strip (frame drawn inside, B-07); the active choice is filled and ticked, never colour alone, and matches aria-pressed.
   Every control is 44px tall (the card pair used to be 42px). */
.cb-board-tools{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3) var(--space-5);margin:0 0 var(--space-3)}
.cb-board-tools .cb-tools-gap{flex:1 1 var(--space-3)}
.cb-tool-group{display:inline-flex;align-items:center;gap:var(--space-2);min-width:0;margin:0}
.cb-tool-label{font-size:var(--text-label);font-weight:var(--weight-medium);color:var(--ink-2);word-break:keep-all}
.cb-seg{display:inline-flex;align-items:stretch;border:0;border-radius:var(--radius-surface);box-shadow:inset 0 0 0 1px var(--line-2);overflow:hidden;background:var(--surface-1)}
.cb-seg button{min-height:var(--control-lg);height:auto;margin:0;padding:0 var(--space-4);border:0;border-radius:0;background:transparent;color:var(--ink-1);
  font-size:var(--text-body);font-weight:var(--weight-medium);word-break:keep-all;overflow-wrap:break-word}   /* min width = the longest word, not one letter */
.cb-seg button+button{box-shadow:inset 1px 0 0 var(--line-2)}
.cb-seg button:hover{background:var(--surface-2)}
.cb-seg button[aria-pressed=true]{background:var(--brand,var(--accent));color:var(--surface-1);font-weight:var(--weight-bold)}
.cb-seg button[aria-pressed=true]::before{content:"\2713";display:inline-block;margin-inline-end:var(--space-1)}   /* its own box: a line may break after the tick, never inside the word */
.cb-board-tools .cb-sort{position:relative;color:var(--ink-2);line-height:var(--leading-normal)}
.cb-board-tools .cb-sort select{width:auto;margin:0;height:var(--control-lg);min-height:var(--control-lg);padding-block:0;font-size:var(--text-body)}
/* This shared sheet loads last: keep sort inputs readable on phones and touch tablets. */
@media(max-width:760px),(pointer:coarse){
  .cb-board-tools .cb-sort select{font-size:var(--text-title);min-height:var(--control-lg);max-width:100%;min-width:0}
}

/* Second horizontal scrollbar above the board (created by board.js where the portal has none) */
.cb-top-scroll{height:20px;overflow-x:scroll;overflow-y:hidden;margin:0 0 12px;scrollbar-color:var(--ink-3) var(--line-1);scrollbar-width:auto;border-radius:var(--radius-control)}
.cb-top-scroll[hidden]{display:none}
.cb-top-scroll .board-top-scroll-track{height:1px}
.cb-top-scroll::-webkit-scrollbar{height:14px}
.cb-top-scroll::-webkit-scrollbar-track{background:var(--line-1);border-radius:var(--radius-control)}
.cb-top-scroll::-webkit-scrollbar-thumb{background:var(--ink-3);border:3px solid var(--line-1);border-radius:var(--radius-control)}

/* Headings stay outside the card scrollport. */
.kanban .lane:not(.is-collapsed){display:flex;flex-direction:column;max-height:max(420px,calc(100vh - 150px));padding:0;overflow:hidden;scrollbar-gutter:auto}
.kanban .lane:not(.is-collapsed) .lane-head{flex:0 0 auto;position:static;margin:0;padding:var(--space-3) var(--space-4);min-height:calc(var(--control-lg) + var(--space-4));gap:var(--space-2);background:var(--accent);color:var(--ink-inverse);border-bottom:1px solid var(--accent-hover);border-radius:var(--radius-surface) var(--radius-surface) 0 0}
.kanban .lane:not(.is-collapsed) .lane-head h2{flex:1;font-size:var(--text-body-lg);font-weight:var(--weight-bold);color:inherit;word-break:keep-all}
.kanban .lane:not(.is-collapsed) .lane-head .lane-dot{display:none}
.kanban .lane:not(.is-collapsed) .lane-head small{background:var(--surface-1);color:var(--accent);font-weight:var(--weight-bold)}
.kanban .lane:not(.is-collapsed) .lane-head .cb-lane-fold{color:var(--ink-inverse);margin:0}
.kanban .lane:not(.is-collapsed) .lane-head .cb-lane-fold:hover{background:var(--accent-hover)}
.cb-lane-body{min-height:0;padding:var(--space-3);overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:auto;scrollbar-color:var(--ink-3) var(--line-1)}
.cb-lane-body::-webkit-scrollbar{width:var(--space-3)}
.cb-lane-body::-webkit-scrollbar-track{background:var(--line-1)}
.cb-lane-body::-webkit-scrollbar-thumb{background:var(--ink-3);border-radius:var(--radius-control);border:2px solid var(--line-1)}
.cb-lane-body .lane-desc{padding-top:0;word-break:keep-all}

/* Lane fold button and collapsed lane: a narrow strip that reads top to bottom - the unfold button, the head-count, the
   step number and the step name (D-04, user request 2026-09-28; count moved up in D-04c, 2026-09-29, so every strip
   has its count at the same height). The name is vertical with every character upright,
   so the 1 of '1차 상담' stands like the Hangul around it; the number reads across. Collapsed strips stretch to the
   board row, so they line up at the top and bottom whatever the name's length. Nothing is clipped: a longer name makes the strip taller. */
.cb-lane-fold{min-height:var(--control-sm);min-width:var(--control-sm);padding:0;margin-left:var(--space-1);border:0;border-radius:var(--radius-control);background:transparent;color:var(--ink-2);font-size:var(--text-body-lg);line-height:1;cursor:pointer}
.cb-lane-fold:hover{background:var(--line-2)}
.lane.is-collapsed{flex:0 0 auto;min-width:calc(var(--control-lg) + var(--space-3));min-height:0;height:auto;align-self:stretch;
  padding:var(--space-3) var(--space-1);cursor:pointer}
.lane.is-collapsed>:not(.lane-head){display:none}
.lane.is-collapsed .lane-head{flex-direction:column;align-items:center;justify-content:flex-start;gap:var(--space-2);padding:0;position:static;margin:0}
.lane.is-collapsed .lane-head h2{display:flex;flex-direction:column;align-items:center;margin:0;writing-mode:horizontal-tb;white-space:normal}
.lane.is-collapsed .lane-head small{order:-1;font-weight:var(--weight-bold)}
/* W3-5A: every folded step's count badge is one width (room for three digits), so 7, 12 and 128 line up */
.lane.is-collapsed .lane-head small{box-sizing:border-box;min-width:calc(3ch + var(--space-2) * 2);text-align:center;font-variant-numeric:tabular-nums}
.lane.is-collapsed .cb-lane-fold{order:-2;margin:0}
.lane.is-collapsed:hover{background:var(--line-1)}
/* every step folded: the strips end with the longest one instead of the board's empty-board height. D-04b: with
   some steps folded, the open steps stretch to the row as well (up to their max height; cards still scroll inside), so
   every step of the board ends at one bottom. An all-open board keeps each step's own height. */
@media (min-width:761px){
  .kanban:not(:has(.lane:not(.is-collapsed))){min-height:0}
  .kanban:has(>.lane.is-collapsed)>.lane{align-self:stretch}
}

/* Card fold button: every card folds to its key facts on its own */
.lead-card{position:relative}
.cb-card-fold{position:absolute;top:8px;right:8px;z-index:2;min-height:28px;padding:0 9px;border:1px solid var(--line-3);border-radius:var(--radius-pill);background:var(--surface-3);color:var(--ink-1);font-size:var(--text-label);font-weight:var(--weight-bold);line-height:1;white-space:nowrap;cursor:pointer}
.cb-card-fold:hover,.cb-card-fold:focus-visible{background:var(--brand,var(--accent));border-color:var(--brand,var(--accent));color:var(--surface-1)}
.lead-card.is-folded .cb-card-fold{top:6px;right:6px}
/* the first line of a card keeps clear of its fold button */
.lead-card .card-agency{padding-right:64px}

/* Folded card: agency · country, name, state flags and the single next action */
.lead-card.is-folded{padding:10px 12px;margin-bottom:8px}
.lead-card.is-folded .card-concern,
.lead-card.is-folded .doc-chips,
.lead-card.is-folded .card-footer,
.lead-card.is-folded .card-memos,
/* the one action that moves the card on stays reachable on a folded card */
.lead-card.is-folded>button:not(.cb-card-fold):not(.card-submit),
.lead-card.is-folded>a,
.lead-card.is-folded>p{display:none}
.lead-card.is-folded h3{margin:4px 0 2px;font-size:var(--text-body-lg)}
/* only the action itself stays: the "다음 할 일" caption is a bare text node, so it is sized away */
.lead-card.is-folded .card-next{border-top:0;margin-top:2px;padding-top:0;line-height:1.4;font-size:0}
.lead-card.is-folded .card-next b{font-size:var(--text-body)}
.lead-card.is-folded .card-next br,.lead-card.is-folded .card-next small{display:none}
.lead-card.is-folded .row{margin:2px 0 0;gap:4px}
.lead-card.is-folded .card-submit{min-height:36px;margin-top:8px;font-size:var(--text-body)}

/* Card aging */
.card-agency .cb-age{font-size:var(--text-label);white-space:nowrap}
.card-agency{flex-wrap:wrap;gap:4px 8px}

/* The card the user came back from */
.lead-card.is-last-opened{outline:3px solid var(--brand,var(--accent));outline-offset:2px;transition:outline-color .6s}

@media (max-width:760px){
  .lane.is-collapsed{flex-basis:52px}
  .cb-lane-fold{min-height:44px;min-width:44px}
  .cb-card-fold{min-height:44px;padding:0 12px;font-size:var(--text-body)}
  .lead-card .card-agency{padding-right:76px}
  /* a phone shows one step at a time: leave room for the page chrome above and the tab bar below */
  .kanban .lane:not(.is-collapsed){max-height:max(360px,calc(100vh - 210px))}
}

/* (2) A card's top line must not move when it folds: the header keeps its height and the space the
   fold pill occupies, folded or not, so "몽골" stays on exactly the same pixel row. */
.lead-card{padding-top:var(--space-4)}
.lead-card.is-folded{padding:var(--space-4) var(--space-4) var(--space-3)}
.lead-card .card-agency{min-height:22px;align-items:center;padding-right:84px;margin-bottom:10px}
.lead-card.is-folded .card-agency{margin-bottom:6px}
.lead-card.is-folded .cb-card-fold{top:8px;right:8px}

/* (3)(4) The evidence tiles stay a 2x2 grid of equal boxes in both portals. board.css loads last,
   so this is the single place the layout is decided. */
.doc-chips{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,max(6em,calc(50% - 4px))),1fr));gap:6px;align-items:stretch}
.doc-chips>*{display:flex;align-items:center;justify-content:flex-start;gap:4px;min-height:30px;padding:4px 8px;
  font-size:var(--text-label);line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box}
.doc-chips>.missing-docs,.doc-chips>[data-chip="missing-docs"]{grid-column:1/-1;white-space:normal}
.lead-card.is-folded .doc-chips{display:none}

/* (7)(8) Buttons that belong together are one size. A row holding two or more buttons splits its
   width evenly and stretches them to a common height, so a pair never reads as "one important
   button and one small one" just because a label is longer. Opt out with .keep-size. */
.row:has(>button+button),.row:has(>button+a.button){align-items:stretch}
.row:has(>button+button)>button:not(.keep-size),
.row:has(>button+a.button)>button:not(.keep-size),
.row:has(>button+a.button)>a.button:not(.keep-size){flex:1 1 0;min-width:112px;max-width:260px}
.row>button,.row>a.button{display:inline-flex;align-items:center;justify-content:center;gap:6px;text-align:center;line-height:1.3}
.dialog-actions>button{min-width:112px}
/* An icon-only control stays square instead of being sized by its glyph. */
.row>button.icon-only,.row>button[data-icon-only]{flex:0 0 auto;min-width:40px;width:40px;padding:0}

/* Touch target without visual weight. Inline affordances (the assignee pill, a memo count, a chip
   filter, a text link inside a row) must stay small to keep dense screens readable, but on a finger
   they need a real target. The pill keeps its size; an invisible overlay carries the tap. Phone widths get it too
   (B TC-05: a phone-width screen without touch emulation left 미팅 시작 → under 44px). */
@media (max-width:760px),(pointer:coarse){
  .cb-assignee,.card-memos,.meeting-link,.cb-inbox-item .cb-chip[role="button"],
  .doc-side button.link,.task-actions button.link{position:relative}
  .cb-assignee::after,.card-memos::after,.meeting-link::after,
  .doc-side button.link::after,.task-actions button.link::after{
    content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:max(100%,var(--control-lg));height:var(--control-lg)}
}

/* One field height across input, select and textarea. A native date control renders 1px taller
   than a text input, which is enough to make a form look uneven. */
input[type="date"],input[type="time"],input[type="datetime-local"]{padding-block:0;line-height:normal}
input[type="date"]::-webkit-datetime-edit,input[type="time"]::-webkit-datetime-edit,input[type="datetime-local"]::-webkit-datetime-edit{padding-block:0}

/* The country stays beside the fold control; the birth date gets the full next line. */
.lead-card .card-agency:has(.card-birth){display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-1);padding-right:0}
.lead-card .card-agency:has(.card-birth) .card-country{padding-right:calc(var(--control-lg) + var(--space-6));min-height:var(--space-6);overflow-wrap:anywhere}
.lead-card .card-agency .card-birth{white-space:normal;overflow-wrap:normal;font-variant-numeric:tabular-nums}
@media(max-width:760px){
 .dialog-actions>button{min-width:0}
}

.lead-card .badge,.lead-card .card-next b{word-break:keep-all;overflow-wrap:anywhere;white-space:normal;text-wrap:pretty}
.lead-card .cb-message-line{display:block}

.lead-card .badge:has(>.cb-message-line){display:inline-flex;flex-direction:column;align-items:flex-start;gap:0}


/* Give the sort chevron a consistent inset from the field edge. */
.cb-board-tools .cb-sort{position:relative}
.cb-board-tools .cb-sort select{appearance:none;padding-inline-end:var(--space-10)}
.cb-board-tools .cb-sort::after{content:"\25BE";position:absolute;right:var(--space-4);top:50%;transform:translateY(-50%);color:var(--ink-3);font-size:var(--text-body);line-height:1;pointer-events:none}

/* Process identity: a consistent icon, step number and connected stage navigation. */
.cb-step-icon{display:inline-flex;flex:0 0 var(--space-6);width:var(--space-6);height:var(--space-6);align-items:center;justify-content:center}
.cb-step-icon svg{width:100%;height:100%}
.cb-step-label{display:flex;flex-direction:column;gap:var(--space-1);line-height:var(--leading-tight)}
.cb-step-order{font-family:var(--font-num);font-size:var(--text-caption);font-weight:var(--weight-medium);opacity:.8}
.kanban .lane:not(.is-collapsed) .lane-head{min-height:calc(var(--control-lg) + var(--space-8))}
.lane.is-collapsed .cb-step-icon{display:none}
.lane.is-collapsed .cb-step-label{writing-mode:vertical-rl;text-orientation:upright;flex-direction:row;align-items:center;gap:var(--space-2);
  line-height:var(--leading-tight)}
.lane.is-collapsed .cb-step-order{writing-mode:horizontal-tb}

/* 16px on any phone or touch screen: iOS zooms into a smaller field on focus. The portals' own
   `input,select,textarea` rule loses to `.cb-board-tools select` above, so the board raises it itself —
   by pointer as well as width, so a wide tablet or a phone held sideways gets it too (Codex M1).
   Kept at the end of the file: it must follow the `.cb-board-tools .cb-seg{height:44px}` layout rule. */
@media (max-width:760px),(pointer:coarse){
  .cb-board-tools select{font-size:var(--text-title)}
  .cb-lane-fold{min-height:var(--control-lg);min-width:var(--control-lg)}   /* D-04: a touch tablet's board too */
  /* The segmented pair sits in a 44px frame, but the frame's border is not the button (Codex hit-test
     note): on touch the buttons themselves are 44px and the frame grows around them. */
  .cb-board-tools .cb-seg{height:auto}
  .cb-board-tools .cb-seg button{height:auto;min-height:var(--control-lg)}
}

/* H5-3 · 공유 진료 기록 (both portals). Threads are separated by rules, not cards; a reply is indented once. */
.rec-list{display:flex;flex-direction:column}
.rec-thread{padding:var(--space-3) 0;border-top:1px solid var(--line-1)}
.rec-thread:first-child{border-top:0}
.rec-item{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}
.rec-item+.rec-item{margin-top:var(--space-3)}
.rec-reply{margin-left:var(--space-5);padding-left:var(--space-3);border-left:2px solid var(--line-2)}
.rec-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-2);font-size:var(--text-label);color:var(--ink-2)}
.rec-head strong{color:var(--ink-1);font-weight:var(--weight-bold)}
.rec-to{color:var(--ink-3)}
.rec-time{font-family:var(--font-num);color:var(--ink-3)}
.rec-body{margin:0;overflow-wrap:anywhere;white-space:normal}
.rec-actions{gap:var(--space-2)}
.rec-history{margin-top:var(--space-1)}
.rec-history summary{cursor:pointer;font-size:var(--text-label);color:var(--ink-2)}
.rec-history ol{margin:var(--space-2) 0 0;padding-left:var(--space-5);display:flex;flex-direction:column;gap:var(--space-2)}
.rec-history li span{font-size:var(--text-caption);color:var(--ink-3)}
.rec-problems,.rec-acl{margin:var(--space-2) 0;padding-left:var(--space-5)}
.rec-doc-meta{font-size:var(--text-label);color:var(--ink-2);overflow-wrap:anywhere}
@media(max-width:750px){.rec-reply{margin-left:var(--space-2)}}
@media(max-width:750px),(pointer:coarse){.rec-history summary{min-height:var(--control-lg);display:flex;align-items:center}
  .rec-doc-meta a{display:inline-block;min-height:var(--control-lg);padding:var(--space-3) 0}}

/* UI refinement step 1 (2026-09-27, Codex CODEX_AGENCY_UI_DESIGN_HANDOFF_20260927.md): one navigation rail for both
   portals. Current item = selected ground + a thin highlight line + 600; hover is a different ground; keyboard focus
   has its own ring. The line is an inset shadow, so it takes no layout space. */
.sidebar{background:var(--nav-bg)}
.nav button{transition:background var(--motion-fast) var(--ease),color var(--motion-fast) var(--ease)}
.nav button:hover{background:var(--nav-hover);color:var(--nav-text)}
.nav button.active,.nav button.active:hover{background:var(--nav-selected);color:var(--nav-text);font-weight:var(--weight-bold);box-shadow:inset 3px 0 0 var(--nav-highlight)}
.nav button:focus-visible{outline:2px solid var(--nav-highlight);outline-offset:-2px}
.nav .icon{color:var(--nav-text-2);opacity:1}
.nav button.active .icon{color:var(--nav-text)}
/* counts on the rail: light pill; red only with critical work (its text then starts with "!") */
.nav .cb-count{background:var(--nav-text);color:var(--ink-1)}
.nav .cb-count.critical{background:var(--danger);color:var(--ink-inverse)}
/* on the phone tab bar the current tab is accent-soft, so a count there is filled green (white on it 8.1:1) */
.bottom-nav .cb-count{background:var(--accent);color:var(--ink-inverse)}
.bottom-nav .cb-count.critical{background:var(--danger)}

/* UI step 2 · the phone board (Codex handoff §5/§6, 2026-09-27). Desktop keeps the horizontal lists. On a phone the
   steps stand in one column and the page scrolls: no horizontal board scroll, no second scrollbar, no scroll inside a
   step. A folded step stays a full-width row with its name and head-count (Trello's collapsed list); its button says
   what it does. Controls of one kind share one grid, so heights, widths and baselines line up in 360-430px. */
@media (max-width:760px){
  .kanban{display:flex;flex-direction:column;gap:var(--space-3);overflow:visible;min-height:0;padding:0 0 var(--space-6)}
  .kanban .lane,.kanban .lane.is-collapsed{flex:none;width:100%;min-width:0;min-height:0;scroll-margin-top:var(--space-4)}
  .kanban .lane:not(.is-collapsed){max-height:none;overflow:visible}
  .kanban .cb-lane-body{overflow:visible;max-height:none;overscroll-behavior:auto;scrollbar-gutter:auto}
  .board-top-scroll,.cb-top-scroll{display:none!important}

  .kanban .lane.is-collapsed{padding:0;border:1px solid var(--line-2);border-radius:var(--radius-surface);background:var(--surface-1)}
  .kanban .lane.is-collapsed .lane-head{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:var(--space-3);
    min-height:calc(var(--control-lg) + var(--space-4));padding:var(--space-2) var(--space-2) var(--space-2) var(--space-4)}
  .kanban .lane.is-collapsed .lane-head h2{flex:1 1 auto;display:flex;flex-direction:row;align-items:center;gap:var(--space-2);writing-mode:horizontal-tb;
    max-height:none;white-space:normal;overflow:visible;font-size:var(--text-body-lg);font-weight:var(--weight-bold);color:var(--ink-1)}
  .kanban .lane.is-collapsed .cb-step-icon{display:inline-flex;color:var(--accent)}
  .kanban .lane.is-collapsed .cb-step-label{writing-mode:horizontal-tb;flex-direction:column;align-items:flex-start;gap:var(--space-1)}
  .kanban .lane.is-collapsed .lane-head small{order:0;margin:0}
  /* W4-9A: the folded step's name takes the row whole - with a zero basis it was squeezed between the count and the fold
     button (~100px) and split letter by letter at 320 / text 200%; now the count and the button wrap below it when the
     name does not fit, and on a phone row the count needs no fixed three-digit width (that is for the desktop column) */
  .kanban .lane.is-collapsed .lane-head small{min-width:0}
  .kanban .lane.is-collapsed .cb-lane-fold{order:1;margin:0}
  .kanban .lane.is-collapsed:hover{background:var(--surface-2)}

  /* step shortcuts: two equal columns; a long name wraps and the row grows with it */
  .lane-jumps{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,max(9.5em,calc(50% - var(--space-1)))),1fr));gap:var(--space-2);margin:0 0 var(--space-4)}
  .lane-jumps button{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;min-width:0;
    min-height:var(--control-lg);margin:0;padding:var(--space-2) var(--space-3);text-align:left;white-space:normal;word-break:keep-all;line-height:var(--leading-tight)}
  .lane-jumps button b{flex:0 0 auto;margin:0}

  /* view settings (D-05): one group per row, its label above and the control across the full width (a label column
     left too little for '빈 단계 접기' at 320px); a segmented control splits its row equally and a label wraps at words */
  .cb-board-tools{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-3);align-items:stretch}
  .cb-board-tools .cb-tools-gap{display:none}
  .cb-board-tools .cb-tool-group{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-1);width:100%}
  .cb-board-tools .cb-sort::after{top:auto;bottom:calc(var(--control-lg) / 2);transform:translateY(50%)}
  .cb-board-tools .cb-seg{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);width:100%}
  .cb-board-tools .cb-seg button{padding:var(--space-2);line-height:var(--leading-tight);white-space:normal}
  .cb-board-tools .cb-sort select{width:100%}
}

/* UI step 2 · §7 the assignee badge beside a patient name, both portals. The visible badge is the inner label: a small
   rounded rectangle (control radius), the same look everywhere. The button around it is transparent and on touch is
   44px tall, so the target is real without the badge growing — and nothing clips it (the label, not the button,
   truncates a long name; the full name stays in title and aria-label). D-02: the label's line height is relative (12px x 1.5 =
   18px, the same 22px badge at normal size), so enlarged text grows the badge instead of crossing its border. */
.cb-assignee,.cb-assignee.none,.cb-inbox-title .cb-assignee,.lead-card h3 .cb-assignee{display:inline-flex;align-items:center;flex:none;
  width:auto;min-width:0;max-width:none;height:auto;min-height:0;margin:0 0 0 var(--space-2);padding:0;border:0;border-radius:var(--radius-control);
  background:transparent;box-shadow:none;overflow:visible;vertical-align:middle;line-height:var(--leading-tight);cursor:pointer}
.cb-assignee:hover,.cb-assignee:focus-visible,.cb-assignee.none:hover,.cb-assignee.none:focus-visible{background:transparent;border-color:transparent}
.cb-assignee::after{content:none}
.cb-assignee-label{display:inline-block;max-width:16ch;padding:1px var(--space-2);border:1px solid var(--line-2);border-radius:var(--radius-control);
  background:transparent;color:var(--accent-ink);font-size:var(--text-label);font-weight:var(--weight-medium);line-height:var(--leading-normal);   /* W5-4A: an owner - outline only */
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cb-assignee.none .cb-assignee-label{border-style:dashed;background:transparent;color:var(--ink-3);font-weight:var(--weight-normal)}
.cb-assignee:hover .cb-assignee-label{border-color:var(--accent)}
.cb-assignee:focus-visible{outline:none}
.cb-assignee:focus-visible .cb-assignee-label{outline:2px solid var(--accent);outline-offset:2px}
@media (max-width:760px),(pointer:coarse){
  .cb-assignee,.cb-assignee.none,.cb-inbox-title .cb-assignee,.lead-card h3 .cb-assignee{min-height:var(--control-lg);min-width:var(--control-lg);justify-content:center}
}

/* UI step 2 · §8 quick filters (hospital board) and assignee filters (agency): small rounded rectangles in an aligned
   grid, label left and count right; work state and assignee are separate groups. Selected = soft green, a green border
   and a tick (never colour alone). On a phone every group is two equal columns. */
.filter-groups{display:grid;gap:var(--space-3);margin:0 0 var(--space-4)}
.filter-groups .filter-chips{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:var(--space-2);margin:0}
.filter-groups .filter-clear{justify-self:start}
.filter-chip,.assignee-filter-chip{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);min-width:0;
  min-height:var(--control-md);padding:var(--space-2) var(--space-3);border:1px solid var(--line-2);border-radius:var(--radius-control);
  background:var(--surface-1);color:var(--ink-2);font-size:var(--text-body);font-weight:var(--weight-medium);text-align:left;
  white-space:normal;word-break:keep-all;line-height:var(--leading-tight)}
.filter-chip:hover,.assignee-filter-chip:hover{background:var(--surface-2);border-color:var(--line-3)}
.filter-chip b,.assignee-filter-chip b{flex:0 0 auto;margin:0 0 0 auto;font-family:var(--font-num);font-variant-numeric:tabular-nums;
  font-size:var(--text-body);font-weight:var(--weight-bold);color:var(--ink-1)}
.filter-chip.on,.assignee-filter-chip.active,.assignee-filter-chip[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent);color:var(--accent-ink);font-weight:var(--weight-bold)}
.filter-chip.on b,.assignee-filter-chip.active b,.assignee-filter-chip[aria-pressed=true] b{color:var(--accent-ink)}
.filter-chip.on::before{content:none}
.filter-chip.on .filter-chip-label::before,.assignee-filter-chip.active::before{content:"✓ "}
.assignee-filter{display:inline-grid;grid-template-columns:repeat(2,minmax(128px,auto));gap:var(--space-2)}
@media (max-width:760px){
  /* two columns, never more; one column once a column would be narrower than 9.5em of its text (Codex 7274d3a:
     enlarged text must not cut a word inside a chip) — the step shortcuts above follow the same rule */
  .filter-groups .filter-chips,.assignee-filter{grid-template-columns:repeat(auto-fit,minmax(min(100%,max(9.5em,calc(50% - var(--space-1)))),1fr));width:100%}
  .filter-chip,.assignee-filter-chip{min-height:var(--control-lg);flex:none}
}
/* TL-01 (B, 2026-09-29): a touch screen wider than a phone (844x390 landscape, a 768 tablet) gets the 44px chips too;
   only the height - the phone's grid stays a phone rule */
@media (pointer:coarse){.filter-chip,.assignee-filter-chip{min-height:var(--control-lg)}}
/* TL-01-A: a touch screen scrolls the board by swiping it; the 20px scrollbar copy above it is no tap target there
   (the phone already hides it) */
@media (pointer:coarse){.board-top-scroll,.cb-top-scroll{display:none!important}}

/* UI step 2 · one board card and step header in both portals (Codex handoff §2/§6): step title 16px/600, the patient
   name 16px/600 first, the next task 14px/600 second, the rest smaller. The card fold control shows a small rounded
   rectangle; its transparent button is the (44px on touch) target, like the assignee badge. */
.kanban .lane:not(.is-collapsed) .lane-head h2{font-size:var(--text-title)}
.lead-card:not(.is-folded) h3{font-size:var(--text-title);font-weight:var(--weight-bold);color:var(--ink-1)}
.lead-card:not(.is-folded) .card-next b{font-size:var(--text-body-lg)}
.eyebrow{font-size:var(--text-label)}
.cb-card-fold,.lead-card.is-folded .cb-card-fold{display:inline-flex;align-items:center;justify-content:center;min-height:0;padding:0;
  border:0;border-radius:var(--radius-control);background:transparent;color:var(--ink-2)}
.cb-card-fold:hover,.cb-card-fold:focus-visible{background:transparent;border-color:transparent;color:var(--ink-1)}
.cb-card-fold-label{display:inline-block;padding:2px var(--space-2);border:1px solid var(--line-2);border-radius:var(--radius-control);
  background:var(--surface-2);font-size:var(--text-label);font-weight:var(--weight-medium);line-height:var(--leading-normal);white-space:nowrap}
.cb-card-fold:hover .cb-card-fold-label{border-color:var(--accent);color:var(--accent-ink)}
.cb-card-fold:focus-visible{outline:none}
.cb-card-fold:focus-visible .cb-card-fold-label{outline:2px solid var(--accent);outline-offset:2px}
@media (max-width:760px),(pointer:coarse){
  .cb-card-fold,.lead-card.is-folded .cb-card-fold{top:0;right:0;min-width:var(--control-lg);min-height:var(--control-lg);padding:0 var(--space-2)}
}

/* UI step 2 · one form vocabulary in both portals (Codex handoff §2 "입력·대화상자"): a field label is 13px/500 and
   what the user types is 400 (the agency label was 14px/600 and its fields inherited that weight); one field height
   (40px, 44px on a phone or touch screen); one focus treatment (2px accent outline + soft ring); and a small button or
   the header assignee button is a control-radius rectangle, never a pill (pills are for badges and counts only). */
label{font-size:var(--text-body);font-weight:var(--weight-medium);color:var(--ink-1)}
label .help,label>small{font-weight:var(--weight-normal)}
input,select,textarea{font-weight:var(--weight-normal)}
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]),select{min-height:var(--control-md)}
input:focus-visible,select:focus-visible,textarea:focus-visible,
input:focus,select:focus,textarea:focus{outline:2px solid var(--accent);outline-offset:1px;box-shadow:0 0 0 4px var(--focus-ring)}
.dialog-actions>button{min-height:var(--control-md)}
button.small,h1 .assignee-button,.detail-meta button.meta-missing{border-radius:var(--radius-control)}
@media (max-width:760px),(pointer:coarse){
  input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=color]),select,.dialog-actions>button{min-height:var(--control-lg)}
}

/* Claude B QA fixes (CLAUDE_B_UI_QA_20260927.md, 2026-09-27) */
/* B-06: every quick filter in a row takes the row's height (the hospital's older flex rule centred them). */
.filter-groups .filter-chips,.assignee-filter{align-items:stretch}
@media (max-width:760px){
  /* B-04: an open step's head keeps the columns of a folded one (same right inset and gap for count and button). */
  .kanban .lane:not(.is-collapsed) .lane-head{padding:var(--space-3) var(--space-2) var(--space-3) var(--space-4);gap:var(--space-3)}
  /* B-05: with text enlarged, a field never pushes the page wider and a tab label wraps inside its tab. */
  select,input:not([type=checkbox]):not([type=radio]){max-width:100%}
  .mobile-tabs button,.bottom-nav button{min-width:0;overflow-wrap:anywhere}
  /* The tab bar keeps each label whole: a column is never narrower than a three-syllable label plus its padding
     (3.2em of the bar's 14px text; the 11-12px labels need about 2.6em), so enlarged text wraps the bar to a second
     row instead of splitting 캘린/더. The page's bottom space follows the bar's real height (--cb-bottom-bar, common.js). */
  .mobile-tabs,.bottom-nav{grid-template-columns:repeat(auto-fit,minmax(min(100%,3.2em),1fr))}
}

/* A value shown as a badge in a panel title (an e-mail, an account) breaks inside its own box instead of pushing the page
   wider (AGENTS 반응형 문장 배치: long values wrap safely inside the value area; hospital settings at 320px, text 200%). */
.panel-title>.badge{min-width:0;max-width:100%;white-space:normal;overflow-wrap:anywhere}

/* Calendar list (CODEX_MOBILE_CALENDAR_REVIEW_20260927.md; tablets: Codex 0620489, 2026-09-27): both portals render the
   desktop grid and a list of dates. Up to 1023px the list shows — phones, and tablets / landscape phones where the
   sidebar left 7 columns of about 70px and the grid cut 11:29 KST and names mid-word (B, 768/844px). From 1024px the
   desktop grid. The rest of the app keeps its 760px phone boundary. Period on one row (‹ title ›), today · date · view
   below. No 7-column grid, no sideways scroll, words never split in the middle. The month overview still follows the
   panel's own width (container query below). */
.cal-mnav,.cal-agenda{display:none}
.cal-panel{container-type:inline-size}
@media (max-width:760px){
  .page-heading button{word-break:keep-all;overflow-wrap:break-word}
}
@media (max-width:1023px){
  .cal-panel>.toolbar,.cal-panel>.cal-scroll,.cal-panel>.legend{display:none}
  .cal-mnav{display:grid;gap:var(--space-3);margin:0 0 var(--space-2)}
  .cal-mnav-period{display:grid;grid-template-columns:var(--control-lg) minmax(0,1fr) var(--control-lg);align-items:center;gap:var(--space-2)}
  .cal-mnav-period button{width:var(--control-lg);min-width:0;min-height:var(--control-lg);height:auto;padding:0;font-size:var(--icon-md);line-height:1}
  .cal-mnav-title{margin:0;min-width:0;text-align:center;font-size:var(--text-title);font-weight:var(--weight-bold);
    line-height:var(--leading-tight);word-break:keep-all;overflow-wrap:normal}
  /* two per row while the date still fits; with enlarged text each control takes its own row (the date is never cut) */
  .cal-mnav-tools{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,9.5em),1fr));gap:var(--space-2)}
  .cal-mnav-tools>*{min-width:0}
  .cal-mnav-tools>button,.cal-mnav-tools>input{width:100%;min-height:var(--control-lg);margin:0}
  .cal-mnav-tools .view-switch{grid-column:1/-1;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-1);margin:0}
  .cal-mnav-tools .view-switch button{min-width:0;min-height:var(--control-lg)}
  .cal-mnav button{word-break:keep-all;overflow-wrap:normal;white-space:normal}
  .cal-mnav-note{margin:0;font-size:var(--text-label);line-height:var(--leading-normal);color:var(--ink-3)}
  .cal-agenda{display:block}
  /* month overview: 7 columns across the panel's padding too; only when each column gets 44px — (7 x 44 - 2 x 16px padding)
     at the panel's 14px text is 19.75em, and with enlarged text the em grows so the date picker takes over */
  .cal-overview{display:none}
  @container (min-width:19.75em){
    .cal-overview{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));margin:0 calc(-1 * var(--space-4)) var(--space-2);
      border-top:1px solid var(--line-1)}
  }
  /* Date first, its count second (Codex CODEX_CALENDAR_DATE_COUNT_HANDOFF_20260927.md): every day cell has the same two
     rows — the date (16px, 600, ink) and a fixed slot under it for the count badge (12px, 500, pale green rounded
     rectangle, 'n건'), empty on a day without appointments — so every week row has the same height. Weeks are
     separated by a light rule and more space than a date and its own count. Today = ring, selected = filled date. */
  .cal-ov-weekday{padding:var(--space-2) 0 var(--space-1);text-align:center;font-size:var(--text-label);color:var(--ink-3)}
  .cal-ov-day,.cal-ov-blank{min-height:64px;border-top:1px solid var(--line-1)}
  .cal-ov-day{display:grid;grid-template-rows:32px 20px;justify-items:center;align-content:center;row-gap:var(--space-1);min-width:0;height:auto;
    margin:0;padding:var(--space-1) 0;border:0;border-top:1px solid var(--line-1);border-radius:0;background:transparent;box-shadow:none;color:var(--ink-1);
    font-size:var(--text-body);font-weight:var(--weight-normal);font-variant-numeric:tabular-nums}
  .cal-ov-num{display:inline-grid;place-items:center;min-width:32px;height:32px;padding:0 2px;border-radius:var(--radius-pill);
    font-size:var(--text-title);font-weight:var(--weight-bold);line-height:1;color:var(--ink-1)}
  .cal-ov-day[data-today] .cal-ov-num{box-shadow:inset 0 0 0 2px var(--accent)}
  .cal-ov-day[aria-pressed=true] .cal-ov-num{background:var(--accent);color:var(--ink-inverse)}
  .cal-ov-count{grid-row:2;align-self:center;padding:2px var(--space-1);border-radius:var(--radius-control);background:var(--success-soft);
    color:var(--success);font-size:var(--text-label);font-weight:var(--weight-medium);line-height:16px;white-space:nowrap}
  .cal-agenda-day{padding:var(--space-3) 0;border-top:1px solid var(--line-1);scroll-margin-top:calc(var(--control-lg) * 2)}
  .cal-agenda-day[aria-current=date]{box-shadow:inset 3px 0 0 var(--accent);padding-left:var(--space-3)}
  .cal-agenda-day[data-closed=day]{background:var(--surface-2)}
  .cal-agenda-date{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-2);margin:0 0 var(--space-2);
    font-size:var(--text-body-lg);font-weight:var(--weight-bold);line-height:var(--leading-tight);color:var(--ink-1);word-break:keep-all}
  .cal-agenda-date .cal-closed{margin:0}
  .cal-tag{display:inline-block;padding:2px var(--space-2);border-radius:var(--radius-control);background:var(--accent-soft);
    color:var(--accent);font-size:var(--text-label);font-weight:var(--weight-medium)}
  .cal-agenda .cal-open-line{margin:0 0 var(--space-2)}
  .cal-agenda-list{display:grid;gap:var(--space-2);margin:0;padding:0;list-style:none}
  .cal-agenda-list li{min-width:0}
  .cal-agenda .event-wrap{display:grid;gap:var(--space-1)}
  .cal-agenda .event{margin:0;min-height:var(--control-lg);padding:var(--space-2) var(--space-3);font-size:var(--text-body);
    white-space:normal;overflow:visible;overflow-wrap:anywhere}
  .cal-agenda .event strong{font-size:var(--text-body)}
  .cal-agenda .event-wrap a.meeting-link.cal-meeting{margin:0;min-height:var(--control-lg);align-items:center}
  .cal-agenda .stay-band{white-space:normal;overflow:visible;overflow-wrap:anywhere}
  .cal-agenda-empty{margin:0;font-size:var(--text-body);color:var(--ink-3)}
  .cal-agenda>.cal-agenda-empty{padding:var(--space-4) 0;border-top:1px solid var(--line-1)}
}

/* B F-01 (2026-09-27): on a short screen (a landscape phone with the keyboard up) the agency dialog's fixed title and
   action row left 42px for the fields. There the whole form scrolls and only the action row stays pinned, so the field
   being typed in gets the height. Hospital dialogs already scroll as a whole. */
@media (max-height:480px){
  .dialog-form{display:block;overflow-y:auto;overscroll-behavior:contain;padding:var(--space-3) var(--space-4) 0}
  .dialog-form>h2{margin-bottom:var(--space-2)}
  .dialog-form .dialog-body{overflow:visible;min-height:auto;margin:0;padding:0}
  .dialog-form .dialog-patient{position:static}
  .dialog-form .dialog-actions{position:sticky;bottom:0;z-index:var(--z-sticky);margin:var(--space-2) calc(var(--space-4) * -1) 0;
    padding:var(--space-2) var(--space-4);border-top:1px solid var(--line-1);background:var(--surface-1)}
}

/* B T-01 (2026-09-27): between the phone layout and a wide desktop (tablets, landscape phones) the top bar squeezed its
   buttons below their words (새로/고침, 로그/아웃, 연세새봄/의원). The bar wraps to a second row instead and its
   controls keep their width; on a wide screen it stays one row of the same height. */
@media (min-width:761px){
  .topbar{flex-wrap:wrap;row-gap:var(--space-2);height:auto;min-height:calc(var(--control-lg) + var(--space-5));padding-block:var(--space-2)}
  .topbar>.cb-fresh,.topbar>.identity{flex:none}
  .topbar>.identity{margin-left:auto}
  .topbar>.date{flex:1 1 auto;min-width:0}
}

/* A panel title's action keeps its width next to a long heading or help text (B text audit, 768/844px: 기/록 작/성);
   the text column gives way instead. */
.panel-title>button,.panel-title>a.button{flex:none}
.panel-title>div{min-width:0}

/* Codex P2-W1: a chip (atomic inline) followed by ' · 상태' — the browser may break right after the chip, so the chip and
   its separator are one no-wrap unit (the unit moves to the next line together; the status text still wraps). */
.cb-keep{white-space:nowrap}

/* B TC-01 / TC-02 (2026-09-27): the clinic-hours day choice (제한 없음 · 휴진 · 시간대 지정) was 32px and a document's
   select box only its own 24px; on a phone or touch screen both take 44px (the box's label carries the tap). */
@media (max-width:760px),(pointer:coarse){
  .hours-mode button{min-height:var(--control-lg)}
  .doc-pick{flex-basis:var(--control-lg);min-width:var(--control-lg);min-height:var(--control-lg);cursor:pointer}
}

/* B R-01 (2026-09-27): with enlarged text a .row button shrank below its longest word (되돌/리기, 비밀/번호, 09:00–18:00/로,
   …에 문의) because overflow-wrap:anywhere let its minimum width fall to one letter. A button never gets narrower than
   its longest word; when that does not fit, the row wraps. A pair still shares the row equally (flex:1 1 0 as before)
   and its 112px minimum grows with the text: max(112px, 8em) is exactly 112px at 13-14px text, 224px at 200%, wider than
   any label word. The refresh button follows the same rule (공통 상단 바 새로/고침). */
.row>button,.row>a.button,.cb-fresh button{min-width:min-content;overflow-wrap:break-word}
.row:has(>button+button)>button:not(.keep-size),
.row:has(>button+a.button)>button:not(.keep-size),
.row:has(>button+a.button)>a.button:not(.keep-size){min-width:max(112px,8em)}

/* NAV contract (CODEX_MOBILE_NAVIGATION_HANDOFF_20260927.md, A 2026-09-28) — the patient page's small sticky header on a
   phone, a landscape phone or a tablet (up to 1023px), shared by both portals. Markup:
     <nav class="cb-detail-nav" aria-label="환자 상세 이동">
       <button type="button" class="cb-detail-nav-back" data-return-entry>← 캘린더</button>
       <div class="cb-detail-nav-title"><strong>환자 이름</strong><small>현재 탭</small></div>
     </nav>
   placed first in #page. The back button returns to the list the patient pages were entered from in one tap (the portal
   keeps that list, its scroll and the element the user left from); the existing "이전 화면" button stays below it.
   The header sticks to the top of the page, one 44px row (a long name takes at most two lines; the full name is the
   page title right below), and anchors scrolled into view land below it. On a phone (760px and below) it runs edge to
   edge over the page's 16px side padding; wider, it sits inside the page padding. Hidden from 1024px. */
.cb-detail-nav{display:none}
@media (max-width:1023px){
  .cb-detail-nav{position:sticky;top:0;z-index:var(--z-sticky);display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;
    gap:var(--space-3);margin:0 0 var(--space-3);padding:var(--space-1) var(--space-4);
    border-bottom:1px solid var(--line-1);background:var(--surface-1)}
  .cb-detail-nav-back{min-height:var(--control-lg);margin:0;padding:0 var(--space-3);font-weight:var(--weight-medium);
    word-break:keep-all;overflow-wrap:break-word}
  .cb-detail-nav-title{display:grid;min-width:0;line-height:var(--leading-tight)}
  .cb-detail-nav-title strong{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;
    font-size:var(--text-body);font-weight:var(--weight-bold);color:var(--ink-1)}
  .cb-detail-nav-title small{font-size:var(--text-label);color:var(--ink-3)}
  html:has(.cb-detail-nav){scroll-padding-top:max(calc(var(--control-lg) + var(--space-4)),calc(var(--cb-sticky-top,0px) + var(--space-3)))}
  /* W4-1A: the body's back button that leads to the same list as the header's (data-same-as-nav) is not shown twice */
  .cb-detail-nav~button.link.back[data-same-as-nav]{display:none}
}
@media (max-width:760px){
  .cb-detail-nav{margin:calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) var(--space-3)}
}

/* C-02: a bar a portal keeps stuck to the top (data-sticky-top, e.g. the hospital's ZIP bar under the patient header)
   also pushes rows scrolled or tabbed into view below it, at any width; --cb-sticky-top is measured by common.js. */
html:has([data-sticky-top]){scroll-padding-top:calc(var(--cb-sticky-top,0px) + var(--space-3))}
@media (max-width:1023px){
  html:has(.cb-detail-nav):has([data-sticky-top]){scroll-padding-top:max(calc(var(--control-lg) + var(--space-4)),calc(var(--cb-sticky-top,0px) + var(--space-3)))}
}

/* D-01 contract (C, user request 2026-09-28) — patient rows that stay inside their panel, shared by both portals'
   dashboards ("최근 고객"). A 5-column table needed 986-1069px in a 474-794px panel and scrolled sideways at every width.
     <ul class="cb-patient-rows">
       <li class="cb-patient-row" data-severity="…" [data-overdue]>
         <div class="cb-pr-who"><span class="customer-line"><button class="link customer" data-patient>이름</button>담당 배지</span><small>국가 · 생년월일</small></div>
         <div class="cb-pr-state">진행 상태 · 담당 주체 · 기한/긴급 배지</div>
         <div class="cb-pr-docs"><span class="doc-chips">자료 칩 4개</span></div>
         <div class="cb-pr-next"><p class="cb-pr-next-text">다음 액션</p><div class="row row-actions">실행 버튼</div></div>
       </li>
     </ul>
   A narrow panel stacks the four parts; from 36em of panel width (about 500px) the row is two columns - name, status and
   documents on the left, the next action and its buttons on the right. Nothing is cut or kept on one line: text wraps at
   words, buttons keep their longest word (R-01). Severity shows as a left rule next to the badges that say it. */
.cb-patient-rows{container-type:inline-size;display:grid;margin:0;padding:0;list-style:none}
.cb-patient-row{display:grid;gap:var(--space-2);min-width:0;padding:var(--space-3) 0;border-top:1px solid var(--line-1)}
.cb-patient-row:first-child{border-top:0}
.cb-patient-row[data-severity=critical],.cb-patient-row[data-overdue]{box-shadow:inset 3px 0 0 var(--danger);padding-left:var(--space-3)}
.cb-patient-row[data-severity=high]:not([data-overdue]){box-shadow:inset 3px 0 0 var(--warning);padding-left:var(--space-3)}
.cb-pr-who{display:grid;gap:2px;min-width:0}
.cb-pr-who .customer-line{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-2);min-width:0}
.cb-pr-who small{font-size:var(--text-label);color:var(--ink-3)}
.cb-pr-state{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-2);min-width:0}
.cb-pr-docs{min-width:0}
.cb-pr-next{display:grid;gap:var(--space-2);align-content:start;min-width:0}
.cb-pr-next-text{margin:0;font-size:var(--text-body);line-height:var(--leading-normal);color:var(--ink-2)}
.cb-pr-next .row-actions{margin:0}
@container (min-width:36em){
  .cb-patient-row{grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-areas:"who next" "state next" "docs next";
    column-gap:var(--space-4);align-items:start}
  .cb-pr-who{grid-area:who}.cb-pr-state{grid-area:state}.cb-pr-docs{grid-area:docs}.cb-pr-next{grid-area:next}
}

/* D-01b: archive rows in the shared row list, both portals (the hospital's first, B 2147ea3/33253c9): the reason reads as
   text next to its end-kind badge, the archived date and who archived it as one small line (a date-time is one unit),
   a pending restore request is marked on the left edge and says so in words. Words wrap, nothing is cut. */
.archive-rows .archive-reason{font-size:var(--text-body);color:var(--ink-2);overflow-wrap:break-word}
.archive-rows .archive-meta{font-size:var(--text-label);color:var(--ink-3)}
.cb-patient-row[data-restore-requested]{box-shadow:inset 3px 0 0 var(--warning);padding-left:var(--space-3)}
.archive-rows .cb-pr-next .cb-chip{white-space:normal;max-width:100%}


/* Explicit first-task reveal: two soft cycles, then a persistent named outline. */
.lead-card.cb-found-target{outline:2px solid var(--accent);outline-offset:2px;scroll-margin-block:calc(var(--space-10) + var(--control-lg) + var(--space-4))}
.cb-found-label{display:block;padding-inline-end:calc(var(--control-lg) + var(--space-2));font-size:var(--text-body);font-weight:var(--weight-bold);color:var(--accent-ink);overflow-wrap:anywhere;margin-bottom:var(--space-2)}
.cb-found-pulse{animation:cb-find-soft var(--motion-find) ease-in-out 2}
@keyframes cb-find-soft{0%,100%{background-color:var(--surface-1)}50%{background-color:var(--accent-soft)}}
@media(prefers-reduced-motion:reduce){.cb-found-pulse{animation:none}}
.cb-found-preview{max-width:min(38rem,calc(100% - var(--space-8)));max-height:80dvh;overflow:auto;padding:var(--space-5);border:1px solid var(--line-2);border-radius:var(--radius-surface);background:var(--surface-1);color:var(--ink-1);box-shadow:var(--shadow-overlay)}
.cb-found-preview::backdrop{background:var(--overlay)}
.cb-found-preview button{min-height:var(--control-lg);margin:var(--space-2);white-space:normal;overflow-wrap:anywhere}
.cb-task-guidance{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr));gap:var(--space-4);margin-block:var(--space-3);font-size:var(--text-body);line-height:var(--leading-normal)}
.cb-task-guidance>div{min-width:0;border-inline-start:var(--space-1) solid var(--line-2);padding-inline-start:var(--space-3)}
.cb-task-guidance p{margin:var(--space-2) 0;overflow-wrap:anywhere;white-space:normal}
.cb-task-guidance .cb-next-condition{color:var(--ink-2);font-size:var(--text-body);font-weight:var(--weight-normal)}
.cb-find-first{min-height:var(--control-lg);white-space:normal;overflow-wrap:anywhere}

.nav .cb-nav-item{display:flex;align-items:stretch;min-width:0;gap:var(--space-1)}
.nav .cb-nav-item>[data-nav]{flex:1;min-width:0;white-space:normal}
.nav .cb-nav-item>.cb-count{flex:none;min-width:var(--control-lg);min-height:var(--control-lg);margin:0;padding:var(--space-1);font-size:var(--text-label);white-space:normal;max-width:5em}

/* Balanced hierarchy: reading and card roles never change the 16px input-title contract. */
body{font-size:var(--text-body)}
.page-heading h1{font-size:var(--text-page);display:flex;align-items:center;gap:var(--space-3);min-width:0;overflow-wrap:anywhere}
.kanban .lane .lead-card h3,.lead-card.is-folded h3,.lead-card:not(.is-folded) h3,.lead-card .card-head h3{font-size:var(--text-card);line-height:var(--leading-tight);overflow-wrap:anywhere}
.panel-title h2,.task-group h2{font-size:var(--text-section)}
.help,.subtitle,.cb-inbox-meta{font-size:var(--text-caption);line-height:var(--leading-normal)}
.cb-banner,.warning,.cb-field-error,.cb-next-condition{font-size:var(--text-body);line-height:var(--leading-normal)}
.cb-ui-icon{display:inline-block;flex:none;width:1.25em;height:1.25em;vertical-align:middle}
.nav .icon,.bottom-nav .icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}
.nav .icon .cb-ui-icon,.bottom-nav .icon .cb-ui-icon{width:var(--icon-md);height:var(--icon-md)}
.page-heading{gap:var(--space-4);flex-wrap:wrap}
.page-heading>div{min-width:0}
.lead-card,.cb-inbox-item,.panel,.cb-task-guidance>div{min-width:0}
.lead-card{padding:var(--space-4);gap:var(--space-3)}
.card-concern,.cb-pr-next-text{font-size:var(--text-body);line-height:var(--leading-normal)}
button,input:not([type=checkbox]):not([type=radio]),select{min-height:var(--control-lg)}
.row>button,.page-heading>button{white-space:normal;overflow-wrap:anywhere}
@media(max-width:760px),(pointer:coarse){input:not([type=checkbox]):not([type=radio]),select{font-size:var(--text-title);min-height:var(--control-lg)}textarea{font-size:var(--text-title)}}

/* Match existing specific compact selectors so effective controls retain the selected 44px target. */
.nav button,.bottom-nav button,.topbar button,.lead-card button,.cb-inbox button,.row button,.panel button{min-height:var(--control-lg)}
button.link,.card-memos,.card-memos.link{min-height:var(--control-lg)}
#app button,#app #my-account,#modal button{min-height:var(--control-lg)}

/* Preserve board/list choice at browser zoom without widening the page. */
.toolbar .view-switch{display:flex;flex-wrap:wrap;min-width:0;max-width:100%;gap:var(--space-1)}
.toolbar .view-switch button{flex:1 1 4em;min-width:0;white-space:normal}

@media(max-width:760px){
  .cb-board-tools .cb-seg{grid-auto-flow:row;grid-auto-columns:auto;grid-template-columns:repeat(auto-fit,minmax(min(100%,var(--control-lg)),1fr))}
}

.cb-lane-fold{min-width:var(--control-lg)}

@media(max-width:240px){.cb-found-label{padding-inline-end:0;padding-block-start:var(--control-lg)}}

@media(max-width:240px){
  .kanban .lane:not(.is-collapsed) .lane-head{flex-wrap:wrap}
  .kanban .lane:not(.is-collapsed) .lane-head h2{flex:1 1 100%;min-width:0}
  .kanban .lane:not(.is-collapsed) .cb-lane-fold{margin-left:0}
  .cb-step-label{min-width:0;overflow-wrap:anywhere}
}

@media(max-width:240px){
  dialog .cb-trial-input-warning{position:static}
  #modal .dialog-actions{display:grid;grid-template-columns:minmax(0,1fr)}
  #modal .dialog-actions>button{width:100%;min-width:var(--control-lg)}
  .hospital-decision-panel .row:has(>button+button)>button:not(.keep-size){min-width:var(--control-lg);max-width:100%;overflow-wrap:anywhere}
}

/* Assigned balanced UI target size also applies to desktop fields, without changing legacy token values. */
#app input:not([type=checkbox]):not([type=radio]),#app select,
#modal input:not([type=checkbox]):not([type=radio]),#modal select{min-height:var(--control-lg)}

/* Extreme browser zoom: document summary rows retain content without widening the patient page. */
@media(max-width:240px){
  .cb-detail-nav{grid-template-columns:minmax(0,1fr);gap:var(--space-2)}
  .cb-detail-nav-back{min-width:0;width:100%}
  .cb-trial-mode .cb-detail-nav{top:calc(var(--control-lg) + var(--space-6));margin-top:var(--space-2)}
  .doc-data-rows{grid-template-columns:minmax(0,1fr)}
  .doc-data-row{display:grid;grid-template-columns:minmax(0,1fr) auto;min-width:0}
  .doc-data-row>.doc-data-what{grid-column:1/-1}
  .doc-data-row>.badge,.doc-data-what .doc-tag{min-width:0;max-width:100%;overflow-wrap:anywhere}
  #patient-body .row:has(>button+button)>button:not(.keep-size){min-width:var(--control-lg);max-width:100%;overflow-wrap:anywhere}
}

/* Shared narrow detail constraints: wrap full status wording and stack equal paired actions. */
@media(max-width:240px){
  #app .badge{white-space:normal;overflow-wrap:anywhere;min-width:0;max-width:100%}
  .stage-badge{flex-wrap:wrap;min-width:0;max-width:100%}
  .row:has(>button+button),.row:has(>button+a.button){display:grid;grid-template-columns:minmax(0,1fr)}
  .row:has(>button+button)>button:not(.keep-size),.row:has(>button+a.button)>button:not(.keep-size),.row:has(>button+a.button)>a.button:not(.keep-size){min-width:var(--control-lg);max-width:100%;overflow-wrap:anywhere}
}
