/* Page shell, in the `layout` layer (see css/layers.css and docs/CSS-ARCHITECTURE.md §3b).

   One DOM, four frames, chosen by media query. Component density inside the frame is a container-query matter (matrix.css).

     desktop          >= 1360 wide, > 480 high    expanded sidebar, 232px             + header + stage
     tablet / desktop 600 – 1359                  72px icon rail                      + header + stage
     phone            < 600                       bottom navigation                   + header + stage
     phone landscape  height <= 480, landscape    56px icon rail                      + one-row header + stage

   The window never scrolls. `.layout` is exactly one dynamic viewport high and `.main` is the single scroller of the page (the
   "stage"); the sticky `.app-header` lives inside it. That keeps the scroll model identical in every frame, lets the browser
   restore, chain and rubber-band scrolling normally, and makes `.main` the one coordinate system every script uses (ui/stage.js).

   The breakpoints below are the strings of domain/layout.js (SHELL_QUERIES); tests/unit/shell-layout.test.mjs fails when they drift.
   The header has two modes, decided by the legacy compact query (<= 900 or short landscape): compact (week stepper + filter toggle
   in one row, day strip below) and wide (filters inline). Both keep the "more" menu for the secondary actions.

   Everything here was MOVED out of styles.css, ui-hardening.css and compact.css (log: design/phase3b/shell-removal-log.md): those
   files are unlayered and always win, so no shell rule may remain in them. Control skins that are shared with other forms
   (.field select / input, buttons) are not shell and stay where they are. */

@layer layout {
  :root {
    --nav-w: var(--layout-sidebar-w);     /* the expanded sidebar (>= 1360); narrower frames override it */
    --gutter-x: 30px;
    --header-gap-y: 8px;
    --safe-t: env(safe-area-inset-top, 0px);
    --safe-r: env(safe-area-inset-right, 0px);
    --safe-b: env(safe-area-inset-bottom, 0px);
    --safe-l: env(safe-area-inset-left, 0px);
  }
  @media (max-width: 1199px) { :root { --gutter-x: 16px; } }
  @media (min-width: 1500px) { :root { --gutter-x: 38px; } }
  @media (min-width: 1200px) and (max-width: 1499px) { :root { --gutter-x: 30px; } }

  /* ======================= frame ======================= */
  .layout {
    display: grid;
    grid-template-columns: var(--nav-w) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "nav main";
    height: 100vh; height: 100dvh;      /* dynamic viewport: follows the mobile browser bars */
    overflow: hidden;
  }
  /* Phase 3d: a docked detail panel is a third column of the shell. The overlay shapes (drawer, sheet) are position:fixed and
     take no grid track, so they never squeeze the stage. ui/detail-host.js sets data-detail from the measured stage width. */
  .layout[data-detail="docked"] {
    /* var(--nav-w) is republished by every frame's media query (72px rail, 56px short landscape, 232px sidebar), so this rule
       must not hardcode a track: doing so would out-rank the rail breakpoint and force the wide sidebar at 1200–1359. */
    grid-template-columns: var(--nav-w) minmax(0, 1fr) auto;
    grid-template-areas: "nav main detail";
  }
  .layout[data-detail="docked"] > .detail-host { grid-area: detail; margin: 12px var(--gutter-r) 12px 0; }
  .sidebar {
    grid-area: nav;
    min-height: 0; overflow: auto; overscroll-behavior: contain;
    display: flex; flex-direction: column; gap: 22px;
    padding: 26px 17px 18px;
    background: var(--surface-panel); border-right: 1px solid var(--border-default);
  }
  .main {
    grid-area: main;
    min-width: 0; min-height: 0;
    overflow-x: hidden; overflow-y: auto; overscroll-behavior-y: contain; scrollbar-gutter: stable;
    padding: 0 0 32px;
    container: shell / inline-size;     /* `cqw` below is the width of the stage, so the content can be capped and centred */
    --gutter-l: var(--gutter-x);
    --gutter-r: var(--gutter-x);
  }
  @supports (width: 1cqw) {
    .main { --gutter-l: max(var(--gutter-x), calc((100cqw - 1850px) / 2)); --gutter-r: var(--gutter-l); }
  }
  /* everything in the stage keeps the gutters; the header paints its background edge to edge and pads itself */
  .search-summary, #view, #notices, .stats, .page-footer { margin-left: var(--gutter-l); margin-right: var(--gutter-r); }
  #view, #dayDutyBoard { scroll-margin-top: calc(var(--app-header-h, 160px) + 8px); }     /* anchors clear the sticky header */
  #view { margin-top: 12px; }
  .page-footer { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; color: var(--text-secondary); font-size: var(--font-size-caption); margin-top: 17px; }
  .page-footer button { border: 0; background: transparent; color: var(--text-secondary); font-size: var(--font-size-caption); padding: 4px 2px; min-height: 28px; text-decoration: underline; }
  .footer-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

  /* ---------- sidebar contents (desktop) ---------- */
  .brand { display: flex; gap: 10px; align-items: center; font-weight: 750; font-size: var(--font-size-section); }
  .brand-mark { display: grid; grid-template-columns: repeat(2, 6px); gap: 4px; padding: 13px; background: var(--surface-accent); border-radius: 11px; }
  .brand-mark i { height: 6px; background: var(--surface-panel); border-radius: 1px; }
  .school { margin-top: 12px; line-height: 1.8; font-size: var(--font-size-caption); color: var(--text-secondary); }
  .side-label { font-size: var(--font-size-caption); color: var(--text-secondary); letter-spacing: .12em; margin-bottom: 9px; }
  .side-bottom { margin-top: auto; border-top: 1px solid var(--border-default); padding-top: 16px; font-size: var(--font-size-caption); color: var(--text-secondary); line-height: 1.8; }
  .offline { display: inline-block; padding: 2px 7px; border-radius: 5px; background: var(--surface-success-soft); color: var(--text-success); margin-bottom: 6px; }
  .nav-list { display: grid; gap: 5px; }
  .nav-btn {
    display: flex; align-items: center; gap: 11px; width: 100%; min-width: 0;
    border: 0; text-align: left; padding: 11px 12px; font-size: var(--font-size-body-sm); border-radius: 9px;
    color: var(--c-56627a-text);
  }
  .nav-btn svg { width: 19px; height: 19px; flex: none; }
  .nav-btn.active { background: var(--surface-accent-soft); color: var(--text-accent); font-weight: 650; }
  .nav-mobile-label { display: none; }
  @media (forced-colors: active) { .day-btn.active, .nav-btn.active { border: 1px solid CanvasText; } }
  @media (prefers-reduced-motion: no-preference) { .sidebar { transition: background-color .25s ease, color .25s ease, border-color .25s ease; } }

  /* ---------- header: one sticky bar, wide mode ---------- */
  .app-header {
    position: sticky; top: 0; z-index: var(--layer-nav);
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--header-gap-y) 12px;
    padding: 10px var(--gutter-r) 8px var(--gutter-l);
    background: var(--surface-page); border-bottom: 1px solid var(--border-default);
    transition: transform .2s ease;
  }
  .app-header.is-hidden { transform: translateY(-100%); }
  .app-header.has-open-panel { max-height: calc(100dvh - 96px); overflow: auto; overscroll-behavior: contain; }
  @media (prefers-reduced-motion: reduce) { .app-header { transition: none; } }
  .app-header .topline, .app-header .toolbar, .app-header .filter-fields { display: contents; }
  /* the title stays for screen readers; the navigation says where you are */
  .topline-title { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .app-logo, .page-subtitle, .today-compact, .mobile-filter-toggle, .mobile-scope { display: none; }
  .app-header .field > span:first-child, .app-header .week-field > span:first-child { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

  .week-field { order: 1; display: flex; flex-direction: column; gap: 5px; flex: 0 1 21rem; min-width: 0; }
  .week-control { display: flex; align-items: center; gap: 5px; min-width: 0; }
  .week-control button { height: auto; min-height: 2.75rem; padding: 5px 11px; }
  .week-control select {
    flex: 1; width: 100%; min-width: 0; max-width: 100%; height: auto; min-height: 2.75rem;
    padding: 6px 11px; font-size: var(--font-size-body); color: var(--text-primary);
    background: var(--surface-panel); border: 1px solid var(--c-d3dbe9-border);
  }
  .app-header .room-field { order: 2; flex: 1 1 155px; min-width: 0; max-width: 230px; }
  .app-header .filter-fields > .today { order: 3; white-space: nowrap; font-size: var(--font-size-body-sm); min-height: 2.75rem; }
  .app-header .search-field { order: 4; margin-left: auto; flex: 1 1 11rem; min-width: min(100%, 11rem); max-width: 270px; }
  .clock { order: 5; text-align: right; font-size: var(--font-size-label); color: var(--text-secondary); min-width: 0; }
  .clock strong { font-size: var(--font-size-body-lg); color: var(--text-primary); font-weight: 650; }
  .top-bar-buttons { order: 6; display: flex; flex: none; gap: 0; }
  .weekstrip { order: 7; flex: 1 0 100%; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 7px; min-width: 0; margin: 0; }
  .day-btn {
    min-width: 0; padding: 8px 5px; border-color: transparent; background: transparent;
    display: flex; justify-content: center; align-items: baseline; gap: 9px; font-size: var(--font-size-body-sm);
  }
  .day-btn strong { font-size: 1.062rem; }
  .day-btn.active { background: var(--surface-emphasis); color: var(--text-on-accent); }
  .day-btn.today:not(.active) { border: 1px solid var(--c-a9bde8-border); color: var(--text-accent); background: var(--surface-accent-soft); }
  .day-btn em { font-size: var(--font-size-caption); font-style: normal; }
  .day-btn.weekend:not(.active) { color: var(--c-747c8d-text); }
  @media (max-width: 1199px) { .weekstrip { gap: 3px; } .day-btn { gap: 6px; } .app-header .search-field { max-width: none; } }
  /* 901 – 1199: the wide header in a narrower stage — no clock, a dot instead of "· 今天", a shorter week select */
  @media (min-width: 901px) and (min-height: 481px) and (max-width: 1199px) {
    .clock { display: none; }
    .app-header { column-gap: 8px; }
    .week-field { flex-basis: 14rem; }
    .app-header .room-field { flex-basis: 130px; }
    .app-header .search-field { flex-basis: 9rem; min-width: min(100%, 9rem); }
    .today-tag { display: none; }
    .day-btn.today::after { content: ''; display: block; width: 5px; height: 5px; margin-top: 1px; border-radius: 50%; background: currentColor; align-self: center; }
  }

  /* bell + "more": the secondary actions live in a popover (all frames) */
  .bar-btn { position: relative; display: inline-grid; place-items: center; width: 38px; height: var(--touch-target-min); padding: 0; border: 0; border-radius: 10px; background: transparent; color: var(--text-primary); }
  .bar-btn[hidden] { display: none; }
  .bar-btn:hover, .bar-btn[aria-expanded="true"] { background: var(--surface-accent-soft); }
  .bar-btn .badge { position: absolute; top: 3px; right: -1px; }
  .app-header .top-actions {
    display: none; position: absolute; right: var(--gutter-r); top: calc(100% + 2px); z-index: 2;
    flex-direction: column; flex-wrap: nowrap; gap: 2px; width: min(260px, calc(100vw - 24px)); max-width: none; margin: 0; padding: 6px;
    background: var(--surface-panel); border: 1px solid var(--border-default); border-radius: var(--radius-lg); box-shadow: var(--shadow-popover);
  }
  .app-header .top-actions.is-open { display: flex; }
  .app-header .top-actions button {
    display: flex; align-items: center; justify-content: flex-start; gap: 10px; flex: none; width: 100%; min-width: 0;
    min-height: var(--touch-target-min); padding: 8px 12px; border: 0; border-radius: var(--radius-md); background: transparent; color: var(--text-primary);
    font-size: 0.9375rem; text-align: left; white-space: nowrap;
  }
  .app-header .top-actions button:hover { background: var(--surface-accent-soft); }
  .app-header .top-actions .clock { display: none; }

  /* 901 – 1359: the wide header sits next to the 72px rail, which has no room for the "机房范围" groups of the sidebar: the scope
     select joins the room and search fields in the bar (compact headers keep it in the filter panel). */
  @media (min-width: 901px) and (min-height: 481px) and (max-width: 1359px) {
    .app-header .mobile-scope { display: flex; flex-direction: column; gap: 5px; order: 2; flex: 1 1 120px; min-width: 0; max-width: 200px; }
  }

  /* ======================= 72px icon rail: tablets and every desktop narrower than 1360 ======================= */
  @media (max-width: 1359px) {
    .layout { --nav-w: 72px; grid-template-columns: var(--nav-w) minmax(0, 1fr); }
    .sidebar { padding: calc(12px + var(--safe-t)) 6px 12px calc(6px + var(--safe-l)); gap: 14px; overflow-x: hidden; }
    .sidebar > div:first-child { display: grid; justify-items: center; }
    .sidebar .brand { font-size: 0; gap: 0; }            /* only the mark: the label would not fit the rail */
    .school, .side-scope, .side-bottom { display: none; }
    .nav-list { gap: 4px; }
    .nav-btn { flex-direction: column; justify-content: center; gap: 4px; min-height: 56px; padding: 6px 2px; font-size: 0.6875rem; line-height: 1.2; text-align: center; border-radius: 10px; overflow-wrap: anywhere; }
    .nav-btn svg { width: 22px; height: 22px; }
    .nav-desktop-label { display: none; }
    .nav-mobile-label { display: block; }
  }

  /* ======================= phone: bottom navigation ======================= */
  @media (max-width: 599px) {
    .layout { --nav-w: 0px; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "main" "nav"; }
    .sidebar { padding: 0; gap: 0; overflow: visible; border-right: 0; border-top: 1px solid var(--border-default); }
    .sidebar > div:first-child { display: none; }
    .nav-list { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 2px; padding: 5px 6px calc(5px + var(--safe-b)); padding-left: calc(6px + var(--safe-l)); padding-right: calc(6px + var(--safe-r)); }
    .nav-btn { min-height: 54px; padding: 6px 1px; font-size: var(--font-size-caption); line-height: 1.3; border-radius: 9px; }
    .nav-btn svg { width: 20px; height: 20px; }
  }

  /* ======================= compact header (<= 900 wide, or short landscape) ======================= */
  @media (max-width: 900px), (max-height: 480px) and (orientation: landscape) {
    :root { --gutter-x: 12px; --header-gap-y: 2px; }
    .main { padding-bottom: 20px; }
    #view { margin-top: 6px; }
    .app-header { gap: 2px 6px; padding: calc(var(--safe-t) + 2px) var(--gutter-r) 2px var(--gutter-l); }
    .app-header .week-field { order: 1; flex: 1 1 0; min-width: 0; margin: 0; width: auto; }
    .today-compact { order: 2; }
    .app-header .mobile-filter-toggle { order: 3; }
    .top-bar-buttons { order: 4; }
    .weekstrip { order: 5; gap: 2px; padding: 0; }
    .clock { display: none; }
    .week-control { gap: 4px; width: 100%; }
    .week-control button { height: var(--touch-target-min); min-width: 30px; padding: 0 4px; font-size: var(--font-size-title-sm); }
    .week-control select { height: var(--touch-target-min); padding: 4px 4px 4px 8px; font-size: var(--font-size-body-sm); }
    .today-compact[hidden] { display: none; }
    .today-compact { display: inline-flex; align-items: center; justify-content: center; flex: none; height: var(--touch-target-min); padding: 0 8px; border: 1px solid var(--c-d4e1f8-border); border-radius: 10px; background: var(--surface-accent-soft); color: var(--text-accent); font-size: var(--font-size-body-sm); }
    .app-header .mobile-filter-toggle { display: inline-flex; align-items: center; justify-content: center; flex: none; width: auto; min-height: var(--touch-target-min); gap: 4px; padding: 0 8px; border: 1px solid var(--border-default); border-radius: 10px; background: var(--surface-panel); color: var(--text-primary); }
    /* the filter fields become a panel under the controls row */
    .app-header .filter-fields { display: none; order: 6; flex: 1 0 100%; min-width: 0; }
    .app-header .toolbar.filters-open .filter-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-top: 13px; padding-top: 12px; padding-bottom: 12px; border-top: 1px solid var(--border-default); }
    .filter-fields .field { width: 100%; max-width: none; min-width: 0; margin: 0; }
    .app-header .filter-fields .field > span:first-child { position: static; width: auto; height: auto; margin: 0; clip: auto; overflow: visible; white-space: normal; }   /* the labels show in the panel */
    .filter-fields .mobile-scope { display: flex; flex-direction: column; gap: 5px; grid-column: 1; }
    .filter-fields input, .filter-fields select { width: 100%; min-width: 0; }
    .filter-fields .search-field { grid-column: 1 / -1; grid-row: 2; margin: 0; max-width: none; }
    .filter-fields > .today { grid-column: 1 / -1; min-height: var(--touch-target-min); font-size: var(--font-size-body-sm); color: var(--text-accent); background: var(--surface-accent-soft); border-color: var(--c-d4e1f8-border); }
    .day-btn { min-height: 46px; padding: 3px 1px; flex-direction: column; align-items: center; justify-content: center; gap: 1px; font-size: var(--font-size-caption); }
    .day-btn strong { font-size: var(--font-size-body-sm); white-space: nowrap; }
    .day-btn em { font-size: 0.6875rem; }
    .day-btn span { font-size: var(--font-size-caption); white-space: normal; line-height: 1.25; max-width: 100%; }
    .today-tag { display: none; }       /* "· 今天" would wrap: a dot under the date instead (aria-current=date keeps it accessible) */
    .day-btn.today::after { content: ''; display: block; width: 5px; height: 5px; margin-top: 1px; border-radius: 50%; background: currentColor; }
    .page-footer { font-size: var(--font-size-caption); }
    .page-footer button { font-size: var(--font-size-label); min-height: var(--touch-target-min); }
  }
  @media (max-width: 400px) { .app-header .toolbar.filters-open .filter-fields { grid-template-columns: minmax(0, 1fr); } .filter-fields .search-field { grid-row: auto; } }
  /* narrow phones (320px): squeeze the controls row instead of wrapping it, which would cost another 48px */
  @media (max-width: 340px) {
    .app-header { column-gap: 3px; }
    .app-header .week-control { gap: 2px; }
    .app-header .week-control button { min-width: 26px; padding: 0 2px; }
    .bar-btn { width: 34px; }
    .app-header .mobile-filter-toggle > span:last-child:not(.badge) { display: none; }   /* chevron */
    .app-header .week-control select { font-size: var(--font-size-label); padding-left: 4px; }
    .today-compact, .app-header .mobile-filter-toggle { padding: 0 6px; }
  }
  @media (max-width: 370px) { .day-btn span { font-size: 0.6875rem; } }

  /* ======================= phone landscape: height is the scarce axis ======================= */
  @media (max-height: 480px) and (orientation: landscape) {
    :root { --gutter-x: 10px; }
    .layout { --nav-w: calc(56px + var(--safe-l)); grid-template-columns: var(--nav-w) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); grid-template-areas: "nav main"; }
    .sidebar { padding: 4px 4px 4px calc(4px + var(--safe-l)); gap: 0; overflow-x: hidden; overflow-y: auto; border-top: 0; border-right: 1px solid var(--border-default); justify-content: center; }
    .sidebar > div:first-child { display: none; }
    .nav-list { display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 0; }
    .nav-btn { flex: none; min-height: 44px; padding: 3px 0; gap: 1px; font-size: 0.625rem; line-height: 1.15; }
    .nav-btn svg { width: 18px; height: 18px; }
    .main { --gutter-l: 8px; --gutter-r: calc(10px + var(--safe-r)); padding-bottom: calc(8px + var(--safe-b)); }
    #view { margin-top: 4px; }
    /* one row: week stepper, today, filters, day strip, bell and menu */
    .app-header .week-field { order: 1; flex: 0 0 176px; }
    .app-header .week-control select { font-size: var(--font-size-label); }
    .app-header .weekstrip { order: 4; flex: 1 1 280px; min-width: 0; padding: 0; }
    .app-header .day-btn { min-height: 40px; padding-top: 1px; padding-bottom: 1px; }
    .app-header .day-btn strong { font-size: var(--font-size-label); }
    .top-bar-buttons { order: 5; margin-left: auto; }
    .app-header .top-actions { top: 100%; }
    .app-header.has-open-panel { max-height: calc(100dvh - 16px); }
  }
  /* ~667px landscape: squeeze the controls so the day strip still fits on the same row */
  @media (max-height: 480px) and (orientation: landscape) and (max-width: 760px) {
    .app-header .week-field { flex-basis: 128px; }
    .app-header .week-control { gap: 2px; }
    .app-header .week-control button { min-width: 30px; }
    .app-header .weekstrip { flex-basis: 236px; gap: 1px; }
    .app-header .day-btn { font-size: 0.6875rem; }
    .app-header .day-btn strong { font-size: var(--font-size-caption); }
    .today-compact, .app-header .mobile-filter-toggle { padding: 0 6px; }
  }

}
