/* ==========================================================================
   responsive.css — ALL breakpoint behaviour, for every page.

   Five bands (Bootstrap-aligned):

     BAND            WIDTH            LAYOUT
     ------------------------------------------------------------------
     wide desktop    >= 1400px        full layout + every column
     desktop         1200 - 1399px    full layout, priority-4 columns drop
     tablet landsc.  992  - 1199px    master + tabbed detail, icon rail
     tablet portrait 768  -  991px    off-canvas nav, context strip
     mobile          <  768px         drill-down, record rows, filter sheet

   Plus two height queries, because 1366x768 and 1024x768 leave very little
   vertical room once browser chrome is subtracted.

   Panels are shown/hidden below 1200px by adding .is-pane-hidden from
   js/workspace.js — that avoids enumerating every pane key in CSS and keeps
   all four pages on one engine.
   ========================================================================== */

.panel.is-pane-hidden {
  display: none !important;
}

/* ==========================================================================
   COLUMN PRIORITY
     p1  always visible
     p2  drops below 768   (below that a grid becomes record rows anyway)
     p3  drops below 1200
     p4  drops below 1400
   ========================================================================== */
@media (max-width: 1399.98px) {
  .data-grid .p4 { display: none; }
}

@media (max-width: 1199.98px) {
  .data-grid .p3 { display: none; }
}

@media (max-width: 767.98px) {
  .data-grid .p2 { display: none; }
}

/* Manual column chooser (toolbar > Columns) always wins over priority. */
.data-grid[data-hide~="market"]    .col-key-market,
.data-grid[data-hide~="currency"]  .col-key-currency,
.data-grid[data-hide~="startDate"] .col-key-startDate,
.data-grid[data-hide~="endDate"]   .col-key-endDate,
.data-grid[data-hide~="updatedBy"] .col-key-updatedBy,
.data-grid[data-hide~="updatedAt"] .col-key-updatedAt,
.data-grid[data-hide~="status"]    .col-key-status {
  display: none;
}

.data-grid--wide  { min-width: 760px; }
.data-grid--xwide { min-width: 1080px; }

/* ==========================================================================
   >= 1600px
   ========================================================================== */
@media (min-width: 1600px) {
  :root {
    --tn-pad-workspace: 14px;
    --tn-gap-panel: 12px;
    --tn-pad-inline: 20px;
  }
}

/* ==========================================================================
   <= 1399px — compact desktop
   ========================================================================== */
@media (max-width: 1399.98px) {
  .topbar__search {
    flex-basis: 240px;
  }

  .user-chip__meta {
    display: none;
  }

  .page-header__title {
    font-size: 20px;
  }
}

/* ==========================================================================
   <= 1199px — TABLET LANDSCAPE
   Every workspace layout collapses to "master + tabbed detail".
   ========================================================================== */
@media (max-width: 1199.98px) {
  :root {
    --tn-pad-workspace: 10px;
    --tn-gap-panel: 8px;
    --tn-h-command: 36px;
    --tn-h-input: 40px;
    --tn-h-input-dense: 36px;
  }

  /* Branding sheds its secondary mark first: the product logo stays, the
     customer logo and its divider go, so search keeps its width. */
  .topbar__brand-divider,
  .topbar__logo--customer {
    display: none;
  }

  /* ---- dialogs at tablet-landscape width ----
     The twelve-column section grid halves rather than collapsing: a section
     that asked for a third of the dialog gets half, and one that asked for
     half gets all of it. Fields inside a section keep their own columns,
     because a three-column row of short controls is still readable here and
     stacking it would double the height of every dialog for nothing. */
  .form-tn__section[data-span="3"],
  .form-tn__section[data-span="4"],
  .form-tn__section[data-span="5"] {
    grid-column: span 6;
  }

  .form-tn__section[data-span="7"],
  .form-tn__section[data-span="8"],
  .form-tn__section[data-span="9"] {
    grid-column: span 12;
  }

  /* The aside stops being a column and becomes the end of the form. Its
     border was the boundary between two columns; there are no longer two. */
  .dlg__split {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--tn-sp-6);
  }

  .dlg__aside {
    padding-left: 0;
    padding-top: var(--tn-sp-6);
    border-left: 0;
    border-top: 1px solid var(--tn-border);
  }

  .dlg {
    padding: var(--tn-sp-6);
  }

  /* The Hot Fix control becomes an icon in a crowded panel header, the same
     way every other control in that row already is. It keeps its name: the
     aria-label and the title were always the accessible name, and the label
     was only ever the visible half of it. */
  .btn-tn--hotfix .btn-tn__label {
    display: none;
  }

  .btn-tn--hotfix {
    width: var(--tn-h-command);
    padding: 0;
    justify-content: center;
  }

  /* --- one engine for all three layouts ---
     Every layout becomes: master list, tab strip, one detail pane. */
  .tab-panel.layout-quad,
  .tab-panel.layout-lr,
  .tab-panel.layout-stack {
    display: flex;
    flex-direction: column;
    gap: var(--tn-gap-panel);
  }

  .layout-quad > .panel--master,
  .layout-quad > .panel-row > .panel--master,
  .layout-lr > .panel--master,
  .layout-stack > .panel--master {
    order: 0;
    flex: 50 1 0;
  }

  .layout-quad > .detail-tabs,
  .layout-lr > .detail-tabs,
  .layout-stack > .detail-tabs {
    display: flex;
    order: 1;
  }

  /* .detail-stack becomes display:contents so its panes join the layout's
     flex flow, but CSS selectors still see the original DOM tree — hence the
     explicit `> .detail-stack > .panel` variants below. */
  .layout-quad > .panel:not(.panel--master),
  .layout-quad > .panel-row > .panel:not(.panel--master),
  .layout-lr > .panel:not(.panel--master),
  .layout-lr > .detail-stack > .panel:not(.panel--master),
  .layout-stack > .panel:not(.panel--master) {
    order: 2;
    flex: 50 1 0;
  }

  .layout-lr > .detail-stack {
    display: contents;
  }

  /* The quad's rows dissolve so their four panels rejoin the collapsed flex
     flow — the same display:contents trick .detail-stack uses above. */
  .layout-quad > .panel-row {
    display: contents;
  }

  /* An even row is two working columns. Below 1200px it would be two cramped
     ones, so it stacks. Unlike the quad's rows it does not dissolve into
     display:contents: there is no collapsed master-plus-tabs flow for its
     panels to rejoin — a document workspace simply goes on stacking. */
  .panel-row--even {
    flex-direction: column;
  }

  /* The same trap the splitter widths fall into just above: flex: 1 1 0 was
     a WIDTH while the row was a row, and turning the row on its side makes
     it a height — both panels collapse to their borders. Stacked, they take
     the height their content needs, which is what every other panel in a
     document workspace does. */
  .panel-row--even > .panel {
    flex: 0 0 auto;
  }

  /* Nothing is side by side any more, so there is no boundary to drag. The
     split widths are neutralised too, or the flex basis meant for a column
     would become a HEIGHT in the stacked layout. */
  .panel-splitter {
    display: none;
  }

  /* The toolbar's panel-position reset goes with them. An action that
     visibly does nothing is worse than no action, so the control leaves the
     toolbar at exactly the width its subject does. */
  .toolbar__split-only {
    display: none;
  }

  .split-pair > :first-child,
  .split-pair > :nth-child(2) {
    flex: 50 1 0;
  }

  .detail-stack > .panel--short {
    max-height: none;
  }

  /* --- chrome --- */
  .topbar__kbd {
    display: none;
  }

  .topbar__search {
    flex-basis: 200px;
    max-width: 300px;
  }

  .context-field__label {
    display: none;
  }

  .detail-groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--tn-sp-6) var(--tn-sp-7);
  }

  .form-tn__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* Six columns instead of twelve: the analytics pair up two-by-two and
     Workspaces keeps a narrow slot beside the first trend rather than
     jumping straight to full width. */
  .tab-panel.home-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .home-grid > .panel--screens    { grid-column: span 2; grid-row: span 1; }
  .home-grid > .home-trend        { grid-column: span 4; }
  .home-grid > .home-upcoming     { grid-column: span 2; grid-row: span 1; }
  .home-grid > .home-revenue      { grid-column: span 4; }
  .home-grid > .home-source       { grid-column: span 3; }
  .home-grid > .home-status       { grid-column: span 3; }
  .home-grid > .home-destinations { grid-column: span 3; }
  .home-grid > .home-pace         { grid-column: span 3; }
  .home-grid > .home-roomtype     { grid-column: span 3; }
  .home-grid > .home-growth       { grid-column: span 3; }
  .home-grid > .home-quarters     { grid-column: span 6; }

  /* Filter row: fits on one line down to 992px, wraps instead of colliding.

     The Reservation Monitor's required Reservation Type is a fourth control
     in this group, and four at the old basis tipped the row onto a second
     line at 1024 — which cost the reservation list about a row of height in
     the band that has the least of it. The search field and the selects each
     give up a little instead, because a select's value is "Package" or
     "Paid" and it never needed 130px to show one. */
  .filter-bar__row {
    flex-wrap: wrap;
  }

  .filter-search {
    flex: 1 1 190px;
    min-width: 150px;
  }

  .filter-field,
  .filter-field--required {
    flex: 1 1 118px;
    min-width: 100px;
  }

  .filter-bar__actions {
    margin-left: auto;
  }
}

/* ==========================================================================
   <= 991px — TABLET PORTRAIT
   Navigation becomes an off-canvas drawer, and the Market select is relocated
   into the context strip by js/responsive.js so the operating context is
   never lost. Dark Mode is not part of that move — it stays in the top bar
   actions at every width.
   ========================================================================== */
/* ==========================================================================
   TABLET LANDSCAPE — 992 to 1199
   The sidebar is a rail here, and expanding it used to take 184px away from
   the workspace: every panel reflowed, the charts re-drew and the split
   ratios were recomputed, all because somebody wanted to read a menu label.

   So the rail keeps a permanent slot in the shell and the sidebar itself is
   lifted out of the flow. Expanding it changes only its own width, and it
   paints over the workspace instead of pushing it. The content box under it
   is byte-identical open or closed, because the shell's padding — not the
   sidebar's width — is what reserves the space.

   Below 992px the sidebar is already a full off-canvas drawer, and above
   1199px it is in-layout on purpose. This band is the only one that needed
   to change, and it reuses that drawer's scrim, Escape and close button
   rather than introducing a second navigation.
   ========================================================================== */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .app-shell {
    padding-left: var(--tn-w-sidebar-collapsed);
  }

  /* Out of the flex flow entirely: nothing it does can resize a sibling.
     The widths themselves still come from layout.css — collapsed is the
     rail, expanded is the full sidebar — so there is one source for them. */
  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
  }

  /* Only the open state lifts off the page; the rail stays flush, exactly as
     it looks today. */
  .app-shell:not(.is-collapsed) .sidebar {
    box-shadow: var(--tn-shadow-lg);
  }

  /* The close affordance the drawer already has, reused here: at this width
     the sidebar is a layer, so it needs a way out that is not the rail
     toggle behind it. */
  .sidebar__brand .sidebar__close {
    display: inline-grid;
  }

  .app-shell.is-collapsed .sidebar__brand .sidebar__close {
    display: none;
  }
}

@media (max-width: 991.98px) {
  :root {
    --tn-h-topbar: 56px;
    --tn-h-command: 38px;
    --tn-h-input: 42px;
    --tn-h-input-dense: 38px;
    --tn-h-row: 38px;
    --tn-pad-inline: 14px;
  }

  /* The whole brand group stands down here: the nav toggle and the Tournate
     wordmark in .topbar__title already carry identity at these widths, and
     the bar needs the room for search and the actions. */
  .topbar__brand {
    display: none;
  }

  /* ---- dialogs at tablet-portrait width ----
     Every section now takes the full width, and a three- or four-column
     field row becomes two. Two, not one: these are short controls beside
     their own labels, and one column would make a forty-field dialog four
     screens long. */
  .form-tn__section[data-span] {
    grid-column: span 12;
  }

  .form-tn__grid[data-cols="3"],
  .form-tn__grid[data-cols="4"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .field.is-span-3,
  .field.is-span-4 {
    grid-column: span 2;
  }

  .dlg__body {
    padding: var(--tn-sp-5) var(--tn-sp-6);
  }

  .dlg__head {
    padding-left: var(--tn-sp-6);
  }

  /* The dialog subtitle goes the way the panel subtitle does: the title and
     the record's status are what identify it, and the toolbar needs the room. */
  .dlg__sub {
    display: none;
  }

  /* A tool window has nowhere to be parked beside on a narrow screen, so it
     becomes an ordinary sheet at the bottom of the viewport. */
  .dlg[data-variant="tool"] {
    inset: auto 0 0 0;
    padding: 0;
  }

  .dlg[data-variant="tool"] .dlg__box {
    width: 100%;
    max-height: 55vh;
    border-radius: var(--tn-radius-lg) var(--tn-radius-lg) 0 0;
  }

  /* The panel header is down to a title and its controls at this width —
     .panel__subtitle has already gone — so the Hot Fix flag goes with it.
     The pressed control and the grid's own ring still state the mode, and
     neither of them is colour alone. */
  .hotfix-flag {
    display: none;
  }

  /* Dark Mode goes icon-only so the right-hand cluster stays compact. */
  .theme-toggle .js-theme-label {
    display: none;
  }

  .theme-toggle {
    width: var(--tn-h-command);
    padding: 0;
    justify-content: center;
  }

  /* ---- off-canvas navigation ---- */
  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--tn-w-sidebar);
    flex-basis: var(--tn-w-sidebar);
    transform: translateX(-100%);
    box-shadow: none;
    transition: transform var(--tn-dur-base) var(--tn-ease);
  }

  .app-shell.is-nav-open .sidebar {
    transform: translateX(0);
    box-shadow: var(--tn-shadow-lg);
  }

  .app-shell.is-collapsed .sidebar {
    width: var(--tn-w-sidebar);
    flex-basis: var(--tn-w-sidebar);
  }

  .app-shell.is-collapsed .sidebar__brand-text,
  .app-shell.is-collapsed .sidebar__search,
  .app-shell.is-collapsed .sidebar__group-label,
  .app-shell.is-collapsed .nav-link__text,
  .app-shell.is-collapsed .nav-link__caret,
  .app-shell.is-collapsed .nav-link__badge {
    display: revert;
  }

  .app-shell.is-collapsed .nav-item.is-open > .nav-sub {
    display: block;
  }

  .app-shell.is-collapsed .nav-link {
    justify-content: flex-start;
    padding: var(--tn-sp-3) var(--tn-sp-4);
  }

  .app-shell.is-collapsed .sidebar__brand {
    justify-content: flex-start;
    padding: 0 var(--tn-sp-5);
  }

  .sidebar__foot {
    display: none;
  }

  .sidebar__brand .sidebar__close {
    display: inline-grid;
  }

  .topbar .topbar__nav-toggle {
    display: inline-grid;
  }

  /* ---- context strip receives the relocated context group ---- */
  .context-strip {
    display: flex;
    height: auto;
    min-height: calc(var(--tn-h-context) + var(--tn-sp-6));
    padding: var(--tn-sp-3) var(--tn-pad-inline);
  }

  .context-strip .topbar__context {
    display: flex;
    gap: var(--tn-sp-3);
    flex: 0 0 auto;
  }

  /* The relocated group keeps its label-over-value shape in the strip */
  .context-strip .context-field__label {
    display: block;
  }

  .topbar__search {
    flex: 1 1 auto;
    max-width: none;
  }

  .user-chip__caret {
    display: none;
  }

  /* ---- page header ---- */
  .page-header {
    flex-wrap: wrap;
    gap: var(--tn-sp-4);
    padding: var(--tn-sp-5) var(--tn-pad-inline);
  }

  .page-header__right {
    margin-left: auto;
  }

  .meta-sep--wide,
  .meta-item--muted {
    display: none;
  }

  /* ---- page context bar wraps ---- */
  .context-bar {
    flex-wrap: wrap;
    gap: var(--tn-sp-4) var(--tn-sp-5);
  }

  .context-bar__field {
    flex: 1 1 240px;
  }

  .context-bar__select {
    flex: 1 1 auto;
    max-width: none;
  }

  /* ---- filter bar: two rows ---- */
  .filter-search {
    flex: 1 1 100%;
    max-width: none;
  }

  .filter-fields {
    flex: 1 1 auto;
    flex-wrap: nowrap;
  }

  .filter-field {
    flex: 1 1 120px;
    min-width: 108px;
  }

  .filter-bar__actions {
    flex: 0 0 auto;
  }

  .panel--master {
    flex: 55 1 0;
  }

  .layout-quad > .panel:not(.panel--master),
  .layout-quad > .panel-row > .panel:not(.panel--master),
  .layout-lr > .panel:not(.panel--master),
  .layout-lr > .detail-stack > .panel:not(.panel--master),
  .layout-stack > .panel:not(.panel--master) {
    flex: 45 1 0;
  }

  /* ---- touch ----
     .icon-btn is deliberately absent: components.css already sizes it from
     --tn-h-command, so it tracks the buttons beside it in every band. Pinned
     to a literal here it matched this band and then leaked into the phone
     band, where the token is 40px and the icon buttons were 38. */
  .grid-action {
    width: 32px;
    height: 32px;
  }

  .data-grid tbody td {
    padding: 0 var(--tn-sp-4);
  }

  .breadcrumb-bar li {
    min-height: 30px;
  }

  .breadcrumb-bar a,
  .breadcrumb-bar [aria-current="page"] {
    display: inline-flex;
    align-items: center;
    min-height: 30px;
    padding-right: var(--tn-sp-2);
  }

  /* The selection toolbar wraps rather than squeezing its controls */
  .selection-bar {
    row-gap: var(--tn-sp-3);
  }

  .selection-bar__filter {
    flex: 1 1 100%;
    max-width: none;
  }

  .form-tn__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .form-tn__field--wide {
    grid-column: span 2;
  }


  .stat-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ==========================================================================
   <= 767px — MOBILE
   ========================================================================== */
@media (max-width: 767.98px) {
  :root {
    --tn-h-topbar: 56px;
    --tn-h-command: 40px;
    --tn-h-input: 44px;
    --tn-h-input-dense: 40px;
    --tn-h-tabs: 46px;
    --tn-h-row: 40px;
    --tn-pad-workspace: 0px;
    --tn-pad-inline: 12px;
    --tn-gap-panel: 0px;
  }

  /* ---- dialogs on a phone ----
     A near-full-screen sheet. Everything else follows from that: one column
     of fields, a toolbar that keeps its commands as icons rather than
     hiding them, and a body that is the only thing scrolling. */
  .dlg {
    padding: 0;
  }

  .dlg__box {
    width: 100%;
    height: 100%;
    max-height: 100%;
    border: 0;
    border-radius: 0;
  }

  .dlg__head {
    gap: var(--tn-sp-3);
    padding: var(--tn-sp-3) var(--tn-sp-3) var(--tn-sp-3) var(--tn-sp-5);
  }

  /* The title gives way to the commands rather than pushing them off the
     edge, and the status badge stands down: the record's own Active field is
     a scroll away, and a clipped half-badge says nothing at all. */
  .dlg__title {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .dlg__status {
    display: none;
  }

  /* The commands stay; only their labels go. Hiding a command outright on a
     phone is how an operator ends up unable to save. */
  .btn-tn.js-cmd .btn-tn__label {
    display: none;
  }

  .btn-tn.js-cmd {
    width: var(--tn-h-touch);
    height: var(--tn-h-touch);
    padding: 0;
    justify-content: center;
  }

  .cmd-region__sep {
    display: none;
  }

  .dlg__body {
    padding: var(--tn-sp-5);
  }

  .form-tn__sections {
    gap: var(--tn-sp-6);
  }

  .form-tn__grid[data-cols="2"],
  .form-tn__grid[data-cols="3"],
  .form-tn__grid[data-cols="4"] {
    grid-template-columns: minmax(0, 1fr);
  }

  .field.is-span-2,
  .field.is-span-3,
  .field.is-span-4 {
    grid-column: span 1;
  }

  /* Touch targets. A dense desktop control is 36px; a thumb needs 44. */
  .dlg .form-tn__control {
    height: var(--tn-h-touch);
    font-size: var(--tn-fs-base);
  }

  /* The dialog is a full-screen sheet at this width, so its tab strip is
     a primary touch target — the same floor .section-tab and .detail-tab
     already take from --tn-h-touch on this band. */
  .dlg-tab {
    height: var(--tn-h-touch);
  }

  .dlg .form-tn__label {
    font-size: var(--tn-fs-md);
  }

  .check-grid[data-cols="3"],
  .check-grid[data-cols="4"],
  .check-grid[data-cols="7"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .check-grid__item {
    min-height: var(--tn-h-touch);
  }

  .dlg__foot {
    flex-direction: column-reverse;
    align-items: stretch;
    padding: var(--tn-sp-4) var(--tn-sp-5);
  }

  .dlg__foot-note {
    text-align: center;
  }

  .dlg__foot-actions .btn-tn {
    flex: 1 1 0;
    height: var(--tn-h-touch);
  }

  /* The editor: the sheet gives up its margins to the text. */
  .editor-meta {
    padding: var(--tn-sp-5);
  }

  .editor-bar {
    padding: var(--tn-sp-3) var(--tn-sp-4);
  }

  .editor-canvas {
    padding: var(--tn-sp-4);
  }

  .editor-sheet {
    padding: var(--tn-sp-6);
  }

  /* Hot Fix is not offered on a phone: below this width the grid IS the
     record list, so there is no cell to type into, and the record/detail
     route is the better way to change a value on a touch screen anyway.
     js/grid-hotfix.js refuses the mode here and removes the control; this
     is the belt to that braces, for a control rendered a frame earlier. */
  .btn-tn--hotfix,
  .hotfix-flag {
    display: none;
  }

  /* ---- topbar: Menu | Tournate | Search | Notif | User ---- */
  .topbar {
    gap: var(--tn-sp-2);
    padding: 0 var(--tn-sp-3);
  }

  .topbar .topbar__title {
    display: block;
    flex: 1 1 auto;
  }

  .topbar__search {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: calc(var(--tn-z-topbar) + 1);
    display: none;
    height: var(--tn-h-topbar);
    padding: var(--tn-sp-3);
    background: var(--tn-surface);
    border-bottom: 1px solid var(--tn-border);
    max-width: none;
  }

  .topbar__search.is-open {
    display: flex;
  }

  /* height comes from --tn-h-context in layout.css, which is already 40px
     at this width — restating it here was a second source for one number. */
  .topbar__search-input {
    padding-right: 44px;
  }

  .topbar__search .topbar__search-close {
    display: inline-grid;
  }

  .topbar .topbar__search-open {
    display: inline-grid;
  }

  .search-results {
    top: calc(100% - var(--tn-sp-2));
    left: var(--tn-sp-3);
    right: var(--tn-sp-3);
    max-height: 60vh;
  }

  .topbar__help {
    display: none;
  }

  .user-chip {
    padding: 0 var(--tn-sp-2);
  }

  /* context strip scrolls horizontally with theme + market */
  .context-strip {
    gap: var(--tn-sp-3);
  }

  .theme-toggle {
    padding: 0 var(--tn-sp-4);
  }

  /* ---- page header ---- */
  .breadcrumb-bar li:not(:nth-last-child(2)) {
    display: none;
  }

  .breadcrumb-bar li + li::before {
    content: "\F284";
    margin-right: var(--tn-sp-2);
  }

  .page-header {
    align-items: center;
    padding: var(--tn-sp-4) var(--tn-pad-inline);
  }

  .page-header__title {
    margin: 0;
    font-size: 19px;
  }

  .page-header__meta {
    gap: var(--tn-sp-2) var(--tn-sp-3);
    font-size: var(--tn-fs-sm);
  }

  /* The CREATE hierarchy only — never a command region, whose buttons are
     not direct children of the header. See js/commands.js. */
  .page-header__right > .btn-tn--ghost {
    display: none;
  }

  .page-header__right > .btn-tn--primary {
    height: var(--tn-h-command);
  }

  /* ---- page context bar ---- */
  .context-bar {
    padding: var(--tn-sp-4) var(--tn-pad-inline);
  }

  .context-bar__field {
    flex: 1 1 100%;
  }

  .context-bar__label {
    flex: 0 0 76px;
  }

  /* ---- toolbar ---- */
  .toolbar {
    gap: var(--tn-sp-2);
    padding: var(--tn-sp-3) var(--tn-pad-inline);
    overflow-x: auto;
    scrollbar-width: none;
  }

  .toolbar::-webkit-scrollbar {
    display: none;
  }

  .toolbar__secondary,
  .toolbar__status {
    display: none;
  }

  .toolbar__group--end {
    margin-left: auto;
  }

  /* ---- filters ---- */
  .filter-bar {
    padding: var(--tn-sp-4) var(--tn-pad-inline);
  }

  .filter-bar__row {
    flex-wrap: nowrap;
    align-items: center;
  }

  .filter-search {
    flex: 1 1 auto;
    min-width: 0;
  }

  .filter-bar__actions {
    display: none;
  }

  .btn-tn--filter {
    display: inline-flex;
    flex: 0 0 auto;
    height: var(--tn-h-input);
  }

  .btn-tn--filter .btn-tn__label {
    display: none;
  }

  #filterDrawerBody .filter-fields {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--tn-sp-6);
  }

  #filterDrawerBody .filter-field {
    flex: 0 0 auto;
    width: 100%;
    min-width: 0;
  }

  #filterDrawerBody .filter-field__label {
    font-size: var(--tn-fs-sm);
  }

  #filterDrawerBody .filter-field__control {
    width: 100%;
    height: var(--tn-h-touch);
  }

  .filter-summary {
    margin-top: var(--tn-sp-3);
    padding-top: var(--tn-sp-3);
  }

  /* ---- panels go full-bleed ---- */
  .panel {
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .panel__head {
    min-height: 44px;
  }

  .panel__subtitle {
    display: none;
  }

  .js-panel-maximise {
    display: none;
  }

  /* ---- grid -> record rows ---- */
  .grid-wrap--alt {
    display: none;
  }

  .record-list {
    display: block;
  }

  /* ---- drill-down ----
     The same .detail-tabs strip switches panes on tablet and inside the
     mobile drill-down, so there is only one tab control to maintain. */
  .drill-bar {
    order: -2;
  }

  .workspace.is-detail-open .drill-bar {
    display: flex;
  }

  .workspace.is-detail-open .page-header,
  .workspace.is-detail-open .section-tabs,
  .workspace.is-detail-open .toolbar,
  .workspace.is-detail-open .filter-bar,
  .workspace.is-detail-open .context-bar {
    display: none;
  }

  .detail-tabs {
    padding: var(--tn-sp-3) var(--tn-sp-4);
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .detail-tabs::-webkit-scrollbar {
    display: none;
  }

  .detail-tab {
    flex: 0 0 auto;
    min-height: var(--tn-h-touch);
    padding: 0 var(--tn-sp-6);
  }

  /* The master list owns the screen until a record is opened; from then on
     the tab strip and exactly one detail pane are shown. Which panels are
     hidden is decided by js/workspace.js via .is-pane-hidden. */
  .workspace:not(.is-detail-open) .detail-tabs {
    display: none;
  }

  .tab-panel.layout-quad,
  .tab-panel.layout-lr,
  .tab-panel.layout-stack {
    gap: 0;
  }

  .layout-quad > .panel,
  .layout-quad > .panel-row > .panel,
  .layout-lr > .panel,
  .layout-stack > .panel {
    flex: 1 1 auto;
    min-height: 0;
  }

  .detail-groups {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--tn-sp-7);
  }

  .detail-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--tn-sp-5);
  }

  .detail-field__value {
    font-size: var(--tn-fs-base);
  }

  /* ---- menus become bottom sheets: the row menu and any shared panel
         (the Column Chooser) use the same treatment ---- */
  .action-menu.is-sheet,
  .popover-menu.is-sheet {
    top: auto !important;
    right: 0 !important;
    bottom: 0 !important;
    left: 0 !important;
    width: 100%;
    min-width: 0;
    max-height: 80vh;
    padding: var(--tn-sp-3) var(--tn-sp-3) calc(var(--tn-sp-6) + env(safe-area-inset-bottom, 0px));
    border: 0;
    border-radius: var(--tn-radius-lg) var(--tn-radius-lg) 0 0;
    box-shadow: var(--tn-shadow-lg);
    overflow-y: auto;
    animation: tn-sheet-up var(--tn-dur-base) var(--tn-ease);
  }

  .action-menu.is-sheet::before,
  .popover-menu.is-sheet::before {
    content: "";
    display: block;
    width: 36px;
    height: 4px;
    margin: var(--tn-sp-2) auto var(--tn-sp-4);
    background: var(--tn-border-strong);
    border-radius: var(--tn-radius-pill);
  }

  .action-menu.is-sheet .menu-item,
  .popover-menu.is-sheet .menu-item {
    min-height: var(--tn-h-touch);
    font-size: var(--tn-fs-lg);
  }

  .popover-menu {
    max-width: calc(100vw - var(--tn-sp-6));
  }

  @keyframes tn-sheet-up {
    from { transform: translateY(16px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
  }







  .form-tn__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--tn-sp-6);
  }

  .form-tn__field--wide {
    grid-column: span 1;
  }

  .form-tn__control {
    height: var(--tn-h-touch);
    font-size: 16px;            /* prevents iOS zoom-on-focus */
  }

  .drawer__panel {
    width: 100%;
  }

  /* Toasts span the phone width rather than floating in one corner */
  .toast-stack {
    bottom: var(--tn-sp-4);
    left: var(--tn-sp-4);
    right: var(--tn-sp-4);
    width: auto;
  }

  /* ---- transfer status relocated into the drill bar ---- */
  .drill-bar .transfer-toolbar {
    flex: 0 0 auto;
    gap: var(--tn-sp-2);
  }

  .drill-bar .dirty-flag {
    padding: 0 var(--tn-sp-3);
  }

  /* Icon-only in the drill bar; the accessible name stays on the title */
  .drill-bar .dirty-flag__text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .drill-bar .js-transfer-save .btn-tn__label {
    display: none;
  }

  .drill-bar .js-transfer-save {
    width: var(--tn-h-command);
    padding: 0;
  }

  /* ---- transfer selection toolbar ---- */
  .selection-bar {
    min-height: 0;
    padding: var(--tn-sp-4) var(--tn-pad-inline);
    row-gap: var(--tn-sp-4);
  }

  .selection-bar__filter {
    flex: 1 1 100%;
    max-width: none;
  }

  .selection-bar__count {
    flex: 0 0 auto;
  }

  .selection-bar__actions {
    flex: 1 1 auto;
    justify-content: flex-end;
  }

  .selection-bar .js-transfer-move {
    height: var(--tn-h-touch);
  }

  .section-tab {
    padding: 0 var(--tn-sp-5);
    min-height: var(--tn-h-tabs);
  }

  /* Below 768px the dashboard is one column: two charts side by side would
     make every axis label illegible, which is worse than scrolling. */
  .tab-panel.home-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .home-grid > .panel--screens,
  .home-grid > .home-trend,
  .home-grid > .home-revenue,
  .home-grid > .home-upcoming,
  .home-grid > .home-source,
  .home-grid > .home-status,
  .home-grid > .home-destinations,
  .home-grid > .home-pace,
  .home-grid > .home-growth,
  .home-grid > .home-roomtype,
  .home-grid > .home-quarters {
    grid-column: 1 / -1;
    grid-row: auto;
  }

  /* Two KPIs to a row rather than five stacked cards: a phone should reach
     the charts without scrolling past a screen and a half of headline
     figures. The value steps down a size so it still fits the narrower card. */
  .metric-card {
    flex-basis: 140px;
    padding: var(--tn-sp-5) var(--tn-sp-5) 0;
  }

  .metric-card__value { font-size: var(--tn-fs-title); }

  .metric-card__spark {
    height: 34px;
    margin: var(--tn-sp-3) calc(var(--tn-sp-5) * -1) 0;
  }

  /* Full width but a shorter viewport: the trends lose a little height so the
     panels below them are still reachable without a long scroll. */
  .home-trend .chart-plot,
  .home-revenue .chart-plot {
    height: 158px;
  }

  .donut-block {
    justify-content: center;
  }

  /* the 2-up grid is already set at <=991; only the padding changes here */
  .stat-row {
    padding: var(--tn-sp-5);
  }
}

/* One KPI per row below 400px: two cards would each be ~140px wide, and a
   six-figure revenue value does not fit in that at any readable size.
   ==========================================================================
   <= 400px — very narrow phones
   ========================================================================== */
@media (max-width: 400px) {
  .metric-card {
    flex-basis: 100%;
  }

  .page-header__right > .btn-tn--primary .btn-tn__label {
    display: none;
  }

  .page-header__right > .btn-tn--primary {
    width: var(--tn-h-command);
    padding: 0;
  }

  .record__dates {
    font-size: var(--tn-fs-xs);
  }

  .theme-toggle .js-theme-label {
    display: none;
  }
}

/* ==========================================================================
   TOUCH / POINTER CAPABILITY
   ========================================================================== */
@media (hover: none) {
  .app-shell.is-collapsed .nav-link[data-label]:hover::after {
    display: none;
  }

  .data-grid tbody tr:hover {
    background: var(--tn-surface);
  }

  .data-grid tbody tr.is-selected:hover {
    background: var(--tn-grid-row-selected);
  }

  .icon-btn,
  .grid-action {
    min-width: 36px;
    min-height: 36px;
  }

  .menu-item {
    min-height: 42px;
  }
}

/* ==========================================================================
   SHORT VIEWPORTS
   ========================================================================== */
@media (max-height: 820px) and (min-width: 768px) {
  :root {
    --tn-h-topbar: 52px;
    --tn-h-context: 36px;
    --tn-h-tabs: 40px;
    --tn-h-input: 36px;
    --tn-h-command: 34px;
    --tn-h-input-dense: 34px;
    --tn-h-panel-head: 40px;
    --tn-h-panel-foot: 26px;
    --tn-h-context-bar: 48px;
    --tn-h-selection-bar: 42px;

    /* Type stays at the larger scale; the row height is what gives the
       density back on a 1366x768 laptop. */
    --tn-h-row: 32px;
    --tn-h-grid-head: 34px;

    --tn-pad-workspace: 8px;
    --tn-gap-panel: 8px;
    --tn-split-master: 54;
    --tn-split-detail: 46;
  }

  .page-header {
    align-items: center;
    padding: var(--tn-sp-3) var(--tn-pad-inline);
  }

  .page-header__left {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--tn-sp-1) var(--tn-sp-6);
  }

  .page-header__title {
    margin: 0;
    font-size: 18px;
  }

  .toolbar {
    min-height: 40px;
  }

  .filter-bar {
    padding-top: var(--tn-sp-3);
    padding-bottom: var(--tn-sp-3);
  }

  /* Visually hidden, NOT display:none — the <label> still names the control. */
  .filter-field__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .panel--master {
    flex: 54 1 0;
  }
}

/* A short tablet in landscape is the tightest realistic case: only one
   detail pane shows, so the master list takes the larger share. */
@media (max-width: 1199.98px) and (max-height: 820px) and (min-width: 768px) {
  .layout-quad > .panel--master,
  .layout-quad > .panel-row > .panel--master,
  .layout-lr > .panel--master,
  .layout-stack > .panel--master {
    flex: 62 1 0;
  }

  .layout-quad > .panel:not(.panel--master),
  .layout-lr > .panel:not(.panel--master),
  .layout-stack > .panel:not(.panel--master) {
    flex: 38 1 0;
  }
}

@media (max-height: 620px) and (min-width: 768px) {
  .page-header__meta {
    display: none;
  }
}

/* ==========================================================================
   THE PAGE TOUR ACROSS THE BANDS  (js/tour.js, css/components.css §24)

   The tour needs very little here, and that is the point: the spotlight is
   measured from the target's own rectangle every time it is painted, so a
   band that moves a panel, hides a column or turns a grid into record rows
   is already accounted for. What is left is the coachmark, which is a fixed
   card and therefore the one part that has to be told about narrow screens
   and short ones.

   The sheet variant itself is in components.css, because js/tour.js decides
   when to use it — a media query cannot tell the bubble it has nowhere to
   go, it can only describe the card once the decision is made.
   ========================================================================== */

/* Tablet landscape and portrait. The workspace is master + tabbed detail
   here, so a 316px card is a much larger share of the screen than it is at
   1600px; it comes down to roughly a quarter of the narrowest case. */
@media (max-width: 1199.98px) {
  .tour-mark {
    width: 288px;
    padding: var(--tn-sp-4) var(--tn-sp-5);
  }

  .tour-mark__body {
    margin-bottom: var(--tn-sp-4);
  }

  .tour-mark__rail {
    margin-bottom: var(--tn-sp-4);
  }
}

/* Phones. The sheet is as wide as the screen, so the message can be as
   long as the desktop one — but it is capped and scrolls rather than
   growing until it covers the thing it is describing. */
@media (max-width: 767.98px) {
  .tour-mark[data-placement="sheet"],
  .tour-mark[data-placement="sheet-top"] {
    padding: var(--tn-sp-5);
  }

  .tour-mark__body {
    max-height: 32vh;
    overflow-y: auto;
  }

  /* Back and Next split the width, because on a sheet they are the whole
     control surface and a thumb should not have to aim. */
  .tour-mark__foot .btn-tn {
    flex: 1 1 0;
    justify-content: center;
    height: 40px;
  }
}

/* Touch. The footer buttons and the corner close are the only things in a
   tour that get pressed; .icon-btn already has its floor from the shared
   rule above, and this gives the same floor to the two named buttons. */
@media (hover: none) {
  .tour-mark__foot .btn-tn {
    min-height: 40px;
  }
}

/* Short viewports — a 1366x768 laptop, or a phone in landscape. The card
   loses padding before it loses the message. */
@media (max-height: 620px) {
  .tour-mark {
    padding: var(--tn-sp-4) var(--tn-sp-5);
  }

  .tour-mark__body {
    max-height: 34vh;
    overflow-y: auto;
    margin-bottom: var(--tn-sp-4);
  }

  .tour-mark__rail {
    margin-bottom: var(--tn-sp-4);
  }
}

/* ==========================================================================
   THE E-MAIL TEMPLATE WORKSPACE ACROSS THE BANDS
   (mail-template.html, css/app.css §3b, js/pages/page-mail.js)

   Three shapes, one for each thing the operator can actually do at that
   width:

     >= 1200   the field library is a column on the left of the document and
               stays there while the letter is worked through
     768-1199  the same column, narrower — a tablet has room for the library
               OR for a usable line length, and the answer is both, tighter
     <  768    the library is a sheet. A permanently narrow left column on a
               phone would leave the document about 200px wide, which is not
               a document; the sheet is opened from the Fields command in the
               editor's own header and closes itself once a field is placed

   Nothing here hides the library outright. Every band keeps click-to-insert
   reachable, because that is the path the feature is specified in terms of
   — see the header of js/mail-editor.js.
   ========================================================================== */

/* Tablet: the library gives up width before the document does, and the
   canvas gives up its gutter before either of them. Its rows are a name
   over a token, and the token is the half that goes — the name is what an
   operator is looking for. */
@media (min-width: 768px) and (max-width: 1199.98px) {
  .mail-workspace {
    grid-template-columns: minmax(180px, 230px) minmax(0, 1fr);
  }

  .field-palette__token {
    display: none;
  }

  .mail-fields > .panel__body {
    padding: var(--tn-sp-4);
  }

  /* Decorative gutter first: at this width every pixel spent on grey is a
     pixel not spent on the letter. The gutter comes down to 12/8 and the
     document takes what that releases — a percentage on top of a reduced
     gutter would hand some of it straight back, and measured at 1024x768
     that came out NARROWER than the 760px cap it replaced. */
  .editor-canvas {
    padding: var(--tn-sp-5) var(--tn-sp-4);
  }

  .editor-sheet,
  .editor-source {
    width: 100%;
    padding: var(--tn-sp-7);
  }
}

/* Phone: one column, and the library is the sheet js/pages/page-mail.js
   moves it into. The workspace is the document. */
@media (max-width: 767.98px) {
  .mail-workspace {
    grid-template-columns: minmax(0, 1fr);
  }

  /* THE WHOLE EDITOR SCROLLS HERE, not just the canvas inside it.

     On a desktop the metadata row and the toolbar are pinned and only the
     document moves, which is what keeps Bold reachable at the foot of a
     long letter. On a phone the metadata row is eight fields in one column
     and takes nearly the whole panel: pinning it left the document a 16px
     window it could not be read or typed in. Measured, at 390x844.

     So below 768px the pinning is dropped and the editor body scrolls as
     one thing — metadata, then toolbar, then letter — which is how a phone
     reads a form anyway. */
  .mail-editor__body {
    overflow-y: auto;
  }

  .editor-canvas {
    flex: 0 0 auto;
    overflow: visible;
  }

  .editor-sheet,
  .editor-source {
    width: 100%;
    min-height: 60vh;
  }

  /* The sheet is a touch surface, so its rows take the touch floor and keep
     the token — there is room for it here, and it is what an operator
     matches against the letter behind the sheet. */
  #fieldsDrawerBody .field-palette__item {
    min-height: var(--tn-h-touch);
  }

  /* The document keeps the whole width; the metadata row above it is
     already one column at this band from the shared form rules. */
  .editor-meta {
    padding: var(--tn-sp-4) var(--tn-sp-5);
  }
}

/* ==========================================================================
   THE STANDARD DIALOG COMMAND REGION ON A PHONE
   (js/dialog.js, css/components.css §11a + §20)

   The rule the standard is written in — status, Save, Save +, Delete,
   Close, in that order — has to survive the band where the labels come off
   the buttons. It does, because the order is decided in the markup and this
   only changes what each slot LOOKS like.

   The lifecycle switch keeps its word when every button beside it has lost
   its label. That is deliberate: the buttons still say what they are with an
   icon, and a switch's icon is its state.
   ========================================================================== */
@media (max-width: 767.98px) {
  /* Two rows on purpose, rather than a row that happens to wrap.

     One row at this width is a 44px touch target per command plus the
     switch — about 300px of the 378 there are — which leaves the record's
     own name six characters. Worse, when it did not quite fit, the LAST
     slot wrapped, so Close alone ended up on a second line and the standard
     five stopped reading as one group.

     So the identity takes the first row and the command region takes the
     second, in one unbroken line, in the same order it is in everywhere
     else. The head is taller; the dialog is a full-screen sheet here, and
     the operator can read both what they are editing and what they can do
     to it. */
  .dlg__head {
    flex-wrap: wrap;
    row-gap: var(--tn-sp-2);
  }

  .dlg__id {
    flex: 1 1 100%;
  }

  .dlg__tools {
    flex: 1 1 100%;
    flex-wrap: nowrap;
    justify-content: flex-end;
  }

  .state-switch {
    height: var(--tn-h-touch);
    padding: 0 var(--tn-sp-3);
    gap: var(--tn-sp-2);
  }

  .state-switch__label {
    min-width: 0;
    font-size: var(--tn-fs-xs);
  }
}
