/* ==========================================================================
   Beauté Fatale Spa — tablet and desktop

   app.css builds a phone: one 480px column, tabs along the bottom, an action
   bar pinned above them. This file takes that apart above 700px and rebuilds
   it as a website — a bar across the top, content in columns, a footer.

   Everything here is additive and lives behind a media query, so the phone
   layout is untouched: nothing below 700px reads a single rule in this file.
   ========================================================================== */

/* Hidden by default so the phone never pays for markup it does not show. */
.desk-bar, .desk-foot { display: none; }

/* --------------------------------------------------------------------------
   Tablet — 700px and up
   -------------------------------------------------------------------------- */

@media (min-width: 700px) {
  /* The 480px ceiling in app.css is what makes a tablet look like a phone
     stranded in the middle of the screen. */
  .app { max-width: none; }

  /* The single biggest tell that a site is a phone app stretched wide: the
     document does not scroll, an inner div does. No browser scrollbar, the
     page cannot be scrolled past, and anything after the scroller — a footer —
     is unreachable. On a wide screen the document scrolls, the way every
     other website does. */
  html, body { height: auto; overflow: visible; }
  .app { height: auto; min-height: 100dvh; overflow: visible; }
  .scroll { overflow: visible; flex: none; min-height: 0; }
  .scroll > .screen { flex: none; }

  .desk-bar {
    display: block;
    flex-shrink: 0;
    background: #fff;
    border-bottom: 1px solid var(--line);
    padding-top: var(--safe-top);
    /* Stays reachable through a long page — the reason the phone keeps its
       tab bar on screen, answered the way a website answers it. */
    position: sticky;
    top: 0;
    z-index: 30;
  }
  .desk-bar-inner {
    display: flex;
    align-items: center;
    gap: 20px;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 12px 24px;
  }

  .desk-brand { flex-shrink: 0; display: flex; align-items: center; }
  .desk-brand .wordmark-logo { height: 30px; width: auto; }

  .desk-links {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    min-width: 0;
    /* Deliberately not a scroll container. An element that scrolls clips its
       content on both axes, and the section panels below hang outside the bar
       — a scrolling row of links cuts them off at the bar's bottom edge. Five
       links fit at every width this file covers. */
    overflow: visible;
    flex-wrap: wrap;
    justify-content: center;
  }

  .desk-link {
    flex-shrink: 0;
    padding: 8px 12px;
    border-radius: 10px;
    font-size: 14px;
    font-weight: 600;
    color: var(--body);
    white-space: nowrap;
  }
  .desk-link:hover { background: var(--cream); color: var(--ink); }
  .desk-link.is-active { color: var(--rose-deep); font-weight: 800; }
  .desk-link .ic { margin-left: 3px; opacity: 0.55; }

  /* ---- Section panels ----
     The bar names five sections; a salon has more pages than that. Rather
     than a hamburger — a phone's answer to a phone's problem — the two
     sections with more behind them open a panel. */
  .desk-link-wrap { position: relative; display: flex; }
  .desk-menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 210px;
    padding: 8px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 14px;
    box-shadow: 0 12px 34px rgba(42, 33, 32, 0.12);
    display: flex;
    flex-direction: column;
    gap: 1px;
    /* Hidden by visibility rather than display so it can fade, and so a
       keyboard tab can still reach the links inside it. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity 120ms ease, transform 120ms ease, visibility 120ms;
    z-index: 40;
  }
  /* focus-within as well as hover: a panel a mouse can open and a keyboard
     cannot is five pages nobody tabbing can reach. */
  .desk-link-wrap.has-menu:hover .desk-menu,
  .desk-link-wrap.has-menu:focus-within .desk-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }
  /* The gap between the button and the panel would otherwise drop the hover
     halfway down. */
  .desk-link-wrap.has-menu::after {
    content: "";
    position: absolute;
    top: 100%; left: 0; right: 0;
    height: 10px;
  }
  .desk-menu-link {
    text-align: left;
    padding: 9px 12px;
    border-radius: 9px;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--body);
    white-space: nowrap;
  }
  .desk-menu-link:hover { background: var(--cream); color: var(--rose-deep); }

  .desk-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
  /* Without both of these the button is the thing flexbox chooses to squeeze,
     and its own label gets clipped inside the pill. */
  /* .btn is width:100% — right for a button a thumb presses at the bottom of
     a phone, wrong for one sitting in a row of icons, where it swallows the
     whole action group and overflows the bar. */
  .desk-book {
    display: none;
    flex-shrink: 0;
    white-space: nowrap;
    width: auto;
    padding-inline: 20px;
  }

  /* The tab bar and the top bar say the same thing; only one of them should
     be on screen. */
  .bottom-nav { display: none; }

  /* One centred measure for every screen, so a page is not re-centred by each
     screen function in its own way. */
  .scroll > .screen {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding-left: 24px;
    padding-right: 24px;
  }
  /* The inner 20px gutters were the phone's margins; with the column centred
     they become a second inset that pulls content off its own edge. */
  .scroll > .screen .pad,
  .scroll > .screen .section-title,
  .scroll > .screen .cat-rail,
  .scroll > .screen .pick-rail,
  .scroll > .screen .shop-rail,
  .scroll > .screen .plan-list,
  .scroll > .screen .menu-list,
  .scroll > .screen .category-body { padding-left: 0; padding-right: 0; }
  .scroll > .screen .home-hero,
  .scroll > .screen .member-promo,
  .scroll > .screen .review-card,
  .scroll > .screen .story-link { margin-left: 0; margin-right: 0; }
  .scroll > .screen .rating-row { padding-left: 0; padding-right: 0; }
  /* Sized for the phone's 20px gutters, which the centred column no longer
     has. */
  .scroll > .screen .story-link { width: 100%; }

  /* The screen header sits inside the same column as its content. */
  .header-slot { background: var(--bg); }
  .header-slot > * {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding-left: 24px;
    padding-right: 24px;
  }
  /* The wordmark and hamburger belong to the phone's header; on a wide screen
     the top bar already carries both. */
  .header-slot .home-head { display: none; }

  /* A pinned action bar is a phone idiom — a thumb reaching the bottom of a
     screen it cannot see past. On a wide screen it reads as a browser
     chrome, so it becomes a bar the page ends with instead. */
  .cta-slot {
    background: #fff;
    border-top: 1px solid var(--line);
    /* Sticks while the page scrolls and settles above the footer at the end,
       so the price and the button stay reachable without covering the last
       thing on the page. */
    position: sticky;
    bottom: 0;
    z-index: 15;
    box-shadow: 0 -6px 24px rgba(42, 33, 32, 0.06);
  }
  .cta-bar {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    background: none;
    border-top: 0;
    padding: 14px 24px;
  }
  .cta-bar--split { box-shadow: none; }
  .cta-bar .btn { max-width: 320px; margin-left: auto; }
  .cta-bar--split .btn { max-width: 260px; margin-left: 0; }

  /* ---- Rails become grids ----
     A row that scrolls sideways is how a phone shows more than fits. Given
     the width, hiding two thirds of the categories behind a swipe is a
     choice against the visitor. */
  .cat-rail {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
    gap: 18px 12px;
    overflow-x: visible;
  }
  .cat-rail-item { width: auto; }

  .pick-rail, .shop-rail {
    display: grid;
    /* auto-fit, not auto-fill: three featured treatments should fill the row
       rather than sit in three quarters of it with a hole on the right. */
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 18px;
    overflow-x: visible;
  }
  /* .shop-rail is a column-flow grid on the phone, which is what sends the
     fifth product into a column of its own at a size all its own. */
  .shop-rail { grid-auto-flow: row; grid-auto-columns: auto; }
  .pick, .shop-rail-item { width: auto; }
  .pick .slot { height: 160px; }

  /* ---- Lists of cards become columns ----
     Only containers whose every child is a card of the same kind. .menu-list
     is not one of them: on the service menu it also holds the intro line and
     the view switch, and gridding it puts those in a column of their own with
     the categories stranded beside them. */
  .svc-list, .plan-list, .treat-grid, .cat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
    align-items: start;
  }
  /* Its children are rows divided by hairlines inside one rounded card —
     side by side the dividers would run into each other. */
  .link-list { max-width: 760px; }

  .home-body { gap: 34px; }
  .home-hero .slot, .hero-track { height: 320px; }
  .detail-hero .slot { height: 360px; border-radius: 20px; }

  .desk-foot { display: block; }
}

/* --------------------------------------------------------------------------
   Desktop — 1024px and up
   -------------------------------------------------------------------------- */

@media (min-width: 1024px) {
  .desk-bar-inner { padding: 14px 32px; gap: 28px; }
  .desk-brand .wordmark-logo { height: 34px; }
  /* Centred when the row fits and scrollable when it does not. Letting it
     overflow instead would push the booking button off the edge — which is
     exactly what happened at 1280px, the commonest laptop width there is. */
  .desk-links { justify-content: center; gap: 6px; }
  .desk-link { font-size: 14.5px; padding: 9px 13px; }
  .desk-book { display: inline-flex; margin-left: 4px; }

  .scroll > .screen { padding-left: 32px; padding-right: 32px; }
  .header-slot > * { padding-left: 32px; padding-right: 32px; }
  .cta-bar { padding-left: 32px; padding-right: 32px; }

  /* A line of body text stops being readable somewhere past 80 characters —
     the eye loses the start of the next line on the way back. Reading and
     form screens keep a measure; browsing screens spread. */
  /* The screen header, the content and the action bar are three separate
     elements that have to read as one column, so the measure is set once on
     the shell they share. */
  .app[data-width="narrow"] .scroll > .screen,
  .app[data-width="narrow"] .header-slot > *,
  .app[data-width="narrow"] .cta-bar { max-width: 760px; }

  /* The hero runs to the edges of the window. A photograph boxed inside the
     same column as the text below it is the single clearest sign that a page
     was drawn for a phone and then widened. */
  /* Written at the same depth as the tablet rule that zeroes these margins:
     that one is three classes deep, so a bare .home-hero here would lose on
     specificity no matter that it comes later in the file. */
  /* ---- Hero ----
     Words on the left, photograph on the right. The dark panel that carries
     the headline over the photo on a phone becomes the left column here, so
     one set of markup serves both and the reading order never changes. */
  .scroll > .screen .home-hero {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    align-items: center;
    gap: 56px;
    padding: 40px 0 56px;
  }
  .home-hero .slot, .home-hero .hero-track { height: 380px; }
  .home-hero .hero-carousel, .home-hero > .slot { order: 2; }
  .home-hero .hero-frame, .home-hero .slot { border-radius: 20px; }
  /* The dark panel is the phone's answer to text sitting on a photograph.
     Beside the photo it becomes plain type on the page background. */
  .home-quote {
    order: 1;
    position: static;
    background: none;
    border-radius: 0;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    overflow: visible;
  }
  /* .panel-dark draws a soft circle in its corner. Against the dark panel it
     is a highlight; with the panel gone it is a pink smudge on the page. */
  .home-quote::before { content: none; }

  .hero-eyebrow {
    display: block;
    font-size: 11.5px; font-weight: 800; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--rose-deep);
    margin-bottom: 18px;
  }
  .home-quote h1 {
    font-size: 46px;
    line-height: 1.1;
    color: var(--ink);
    letter-spacing: -0.4px;
    max-width: 12ch;
  }
  .hero-lede {
    display: block;
    margin-top: 20px;
    max-width: 46ch;
    font-size: 15px; font-weight: 500; line-height: 1.65; color: var(--body);
  }
  .hero-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 28px; }
  .home-quote .pill-cta { margin: 0; }
  .pill-cta--ghost {
    display: inline-flex;
    background: #fff;
    color: var(--ink);
    border: 1.4px solid var(--line);
  }
  .pill-cta--ghost:hover { border-color: var(--rose-deep); color: var(--rose-deep); }
  .hero-rating {
    display: flex; align-items: center; gap: 7px;
    margin-top: 26px;
    font-size: 13px; font-weight: 600; color: var(--muted);
  }
  .hero-rating .rating-stars { display: flex; color: var(--gold); }
  .hero-rating strong { color: var(--ink); font-weight: 800; }

  /* ---- Browse services ----
     Six icons spread thin across a wide row read as six lost symbols. Given
     the width they become cards that say what the category is and how much of
     it there is — the two questions a visitor has before clicking. */
  .cat-rail { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
  .cat-rail-item {
    align-items: flex-start;
    text-align: left;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 16px;
    padding: 20px;
    gap: 12px;
    height: 100%;
    transition: border-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
  }
  .cat-rail-item:hover {
    border-color: var(--rose-soft);
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(42, 33, 32, 0.06);
  }
  .cat-rail-item .cat-icon { width: 42px; height: 42px; border-radius: 13px; }
  /* .cat-rail-item span is centred for the phone's icon tiles; every line in
     a card reads from the same left edge instead. */
  .cat-rail-item span { text-align: left; }
  .cat-rail-item > span:not([class]) {
    font-size: 15px; font-weight: 800; color: var(--ink); line-height: 1.3;
  }
  .cat-rail-blurb {
    display: block;
    font-size: 12.5px; font-weight: 500; line-height: 1.55; color: var(--muted);
    /* Pushes the count to the bottom so the row of cards ends on one line
       however long the descriptions run. */
    flex: 1;
  }
  .cat-rail-count {
    display: flex; align-items: center; gap: 3px;
    font-size: 12.5px; font-weight: 700; color: var(--rose-deep);
  }

  /* ---- Reviews ----
     Centred, because the section is a claim about the salon rather than a
     list to work through. */
  /* The flex row is inside .section-title, so centring the wrapper alone
     leaves the heading on the left. */
  .home-reviews .section-title-row { justify-content: center; }
  .home-reviews .section-title { text-align: center; }
  .home-reviews .rating-row { justify-content: center; }
  /* The three cards below are the sample; a link to more sits at the bottom
     of the page, not in the middle of a centred heading. */
  .home-reviews .see-all { display: none; }
  .review-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
    align-items: start;
  }
  .review-row .review-card { display: block; margin: 0; max-width: none; padding: 20px; }
  .review-row .review-card:nth-child(n + 2) { display: block; }
  .review-row .review-card .rating-stars { display: flex; color: var(--gold); margin-bottom: 10px; }
  .review-row blockquote { font-size: 13.5px; }

  /* ---- Our Story ----
     Photograph and invitation side by side, in a card that reads as a panel
     rather than as the phone's one-line link. */
  .story-link {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr);
    align-items: center;
    gap: 40px;
    max-width: none;
    padding: 22px;
    text-align: left;
  }
  .story-link .slot { width: 100%; height: 260px; border-radius: 14px; }
  .story-link .slot img { width: 100%; height: 100%; object-fit: cover; }
  .story-link-text { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
  .story-link-text .eyebrow { display: block; }
  .story-link-text strong {
    font-family: var(--font-display);
    font-size: 25px; font-weight: 700; line-height: 1.25; color: var(--ink);
  }
  .story-link-text > span:not([class]) { display: none; }
  .story-link-more {
    display: flex; align-items: center; gap: 4px;
    font-size: 13.5px; font-weight: 700; color: var(--rose-deep);
  }
  /* The chevron at the far end belongs to the phone's single-line row. */
  .story-link > .ic { display: none; }

  /* Four featured treatments across, fixed rather than auto-fit: a salon that
     features three should leave the fourth slot visibly empty in the editor,
     not have the row silently re-space itself into thirds. */
  .pick-rail { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }

  /* ---- Products ----
     A retail photograph is shot square and on white. Given a 550px-wide cell
     and a fixed 140px height, the bottle ends up a sliver in a letterbox —
     the ratio has to come from the cell, not from a number set for a phone. */
  .shop-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px; }
  .shop-grid .product-media,
  .shop-grid .product .slot,
  .shop-rail-item .product-media,
  .shop-rail-item .slot {
    height: auto;
    aspect-ratio: 1 / 1;
  }
  .shop-grid .product .slot img,
  .shop-rail-item .slot img {
    width: 100%;
    height: 100%;
    /* contain, not cover: a product shot cropped to fill loses the top of the
       bottle, and the white ground is meant to be seen. */
    object-fit: contain;
    padding: 14px;
  }
  .shop-grid .product .slot { background: #fff; border: 1px solid var(--line); }
  .shop-grid .product strong { font-size: 14px; }
  .shop-rail { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 22px; }
  .pick .slot { height: 175px; }

  /* ---- Things that should not be as wide as the page ----
     A quotation, a video and a one-line link do not become better for being
     1180px across; they become a phone layout that was stretched. Each keeps
     the width its content actually asks for. */
  .video { max-width: 880px; margin-inline: auto; }
  .review-card { max-width: 760px; }
  .rating-row { max-width: 760px; }
  .story-link { max-width: 760px; width: 100%; }
  .member-promo { max-width: 1000px; margin-inline: auto; }

  .plan-list { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
  .svc-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
  .treat-grid, .cat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
  .cat-cell .slot { height: 190px; }
  .treat-cell .slot { height: 150px; }
  /* The switch lines up with the right edge of the grid it controls; the
     intro line keeps a readable measure rather than stretching to meet it. */
  .view-bar .lede { max-width: 560px; }

  /* Two panels reading side by side: what is being chosen on the left, what
     it comes to on the right, following the page down. */
  .member-promo { padding: 32px 36px 34px; }
  .member-promo h2 { font-size: 24px; }

  .section-eyebrow {
    display: block;
    font-size: 11px; font-weight: 800; letter-spacing: 0.16em;
    text-transform: uppercase; color: var(--rose-deep);
    margin-bottom: 8px;
  }
  .section-title h2 { font-size: 27px; letter-spacing: -0.2px; }
  .section-title p { font-size: 13.5px; margin-top: 6px; }
  .home-body { gap: 64px; padding-bottom: 16px; }

  /* ---- Membership banner ----
     The claim and the way to act on it read side by side rather than stacked,
     which is what the width is for. */
  .member-promo {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto auto auto;
    align-items: start;
    column-gap: 48px;
    row-gap: 10px;
    padding: 40px 44px;
  }
  /* Placed explicitly: left to auto-placement the button lands in the first
     row beside the crown rather than beside the whole block. */
  .member-promo .ic { grid-area: 1 / 1; }
  .member-promo h2 { grid-area: 2 / 1; max-width: 22ch; margin: 0; }
  .member-promo p { grid-area: 3 / 1; margin: 0; max-width: 52ch; }
  .member-promo .link-gold {
    grid-area: 1 / 2 / 4 / 3;
    align-self: center;
    background: var(--gold);
    color: var(--ink);
    padding: 13px 26px;
    border-radius: 12px;
    font-weight: 800;
    white-space: nowrap;
  }
  .member-promo .link-gold:hover { background: var(--gold-deep); color: #fff; }

  /* The homepage the salon asked for ends at Our Story: the video and the
     shop carousel have their own pages, and both are reachable from the bar
     above and the footer below. They stay in the markup for the phone. */
  .home-body > .section:has(.shop-rail),
  .home-body > .section:has(.video),
  .home-body > .section:has(.vc-card) { display: none; }

  /* ---- Treatment and product pages ----
     On a phone the photo fills the width and the description scrolls up over
     it. Given two columns, the picture and the reason to book can be read at
     once, and the price no longer sits a screen away from the photograph. */
  .screen--flush {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 12px 44px;
    align-items: start;
  }
  /* Written at the depth of app.css's `.scroll > .screen--flush { padding-top:
     0 }`, which strips the gap so the phone's photo can run under the notch.
     A bare .screen--flush here would lose on specificity, not on order. */
  .scroll > .screen--flush { padding-top: 32px; padding-bottom: 40px; }
  .screen--flush .detail-hero { grid-column: 1; grid-row: 1; }
  .screen--flush .product-thumb-row { grid-column: 1; grid-row: 2; padding: 0; }
  .screen--flush .detail-body {
    grid-column: 2;
    grid-row: 1 / -1;
    /* The overlap and the rounded lip belong to the phone, where the panel
       slides up over the photo. Side by side they read as a seam. */
    margin-top: 0;
    border-radius: 18px;
    border: 1px solid var(--line);
    background: #fff;
    padding: 28px;
  }
  .screen--flush .detail-title { font-size: 27px; margin: 0; }

  /* ---- Detail body ----
     The phone stacks these with whatever margins each element brought. Given
     a panel of its own, the page needs one rhythm rather than seven — a gap
     on the column sets the spacing between every section at once. */
  .screen--flush .detail-body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
  }
  .screen--flush .detail-body > * { margin: 0; }
  .screen--flush .product-brand { color: var(--muted); font-size: 14px; }
  .screen--flush .detail-facts { display: flex; flex-wrap: wrap; gap: 10px; }
  .screen--flush .detail-copy { font-size: 15px; line-height: 1.7; }
  .screen--flush .rule { width: 100%; margin: 4px 0; }
  /* The rule already separates it; the extra gap above would read as a
     second, wider divider. */
  .screen--flush .how-to { margin-top: -4px; }
  .screen--flush .how-to .eyebrow { margin-bottom: 6px; }
  .screen--flush .how-to p { font-size: 14.5px; line-height: 1.7; color: var(--body); }

  /* A product is photographed on white; the panel says where the photo ends
     and the page begins. */
  .detail-hero--product {
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 18px;
    overflow: hidden;
  }
  .detail-hero--product .slot { height: 420px; border-radius: 0; }
  .detail-hero--product .slot img { padding: 36px; }
  .screen--flush .product-thumb-row { padding: 12px 0 0; }

  /* The price and the button belong to the panel on the right, not to the
     two ends of a 1180px bar. Sat under that column, the bar reads as part of
     what it is pricing. */
  .app[data-width="wide"] .cta-bar--split {
    max-width: 620px;
    margin-left: auto;
    margin-right: 0;
    padding-right: 32px;
  }
  /* The top bar carries the way back; a button floating on the photograph is
     the phone's answer to not having one. */
  .screen--flush .detail-hero > .icon-btn { display: none; }

  /* ---- Booking flow ----
     A sequence of decisions, one after another. Widening it past a readable
     measure would only spread each choice further from the next. */
  .flow-body, .confirm, .cart-body { max-width: 780px; margin-inline: auto; width: 100%; }
  .book-list { padding-left: 0; padding-right: 0; }
  /* Six across rather than three: a morning and an afternoon fit on one row,
     so choosing a time stops being a scroll. */
  .slot-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.desk-foot {
  margin-top: 48px;
  background: var(--ink);
  color: rgba(255, 255, 255, 0.72);
}
.desk-foot-inner {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 52px 24px 40px;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.2fr;
  gap: 40px 32px;
  align-items: start;
}
.desk-foot-brand .wordmark-logo {
  height: 34px;
  width: auto;
  /* The logo is dark ink on a pale ground; on the dark footer it needs to be
     inverted rather than sitting in an invisible rectangle. */
  filter: brightness(0) invert(1);
  opacity: 0.92;
  margin-bottom: 16px;
}
.desk-foot-brand p { font-size: 13px; line-height: 1.7; max-width: 34ch; }

.desk-foot-group h3 {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 14px;
}
.desk-foot-link {
  display: block;
  padding: 5px 0;
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.72);
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.desk-foot-link:hover { color: #fff; }

.desk-foot-visit p { font-size: 13px; line-height: 1.7; padding: 3px 0; }
.desk-foot-visit a { color: rgba(255, 255, 255, 0.72); text-decoration: none; }
.desk-foot-visit a:hover { color: #fff; }
.desk-foot-hours-list { margin-top: 14px; }
.desk-foot-hours {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  font-size: 13px;
  padding: 3px 0;
}
.desk-foot-hours span:last-child { color: rgba(255, 255, 255, 0.55); white-space: nowrap; }

.desk-foot-legal {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  max-width: 1180px;
  margin: 0 auto;
  padding: 18px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
}
.desk-foot-legal-links { display: flex; gap: 18px; flex-wrap: wrap; }
.desk-foot-legal-links .desk-foot-link { padding: 0; font-size: 12px; }

@media (max-width: 1000px) {
  .desk-foot-inner { grid-template-columns: 1fr 1fr; }
  .desk-foot-brand { grid-column: 1 / -1; }
}
