*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
/* ===========================================================================
   ONE PAGE WIDTH, IN ONE PLACE
   ---------------------------------------------------------------------------
   v67 point 16. There were THREE containers deciding how wide the page is, and
   they did not agree:

       .wrap        max-width 1180px, padding 0 40px   the sections and the footer
       .nav .in     max-width 1180px, padding 16px 40  the header
       .wrap-hero   max-width 1340px, padding 0 40px   the hero photograph

   So the header's content sat 80px inside the photograph on both sides at every
   width above 1340, and 50px inside it at 1280. Measured, not guessed: at 1440
   the logo's left edge was at 170 and the photograph's at 90; the last link
   ended at 1270 and the photograph at 1350. The footer had exactly the same
   80px, because the footer is a .wrap.

   THE FIX IS NOT A NUMBER ON THE BAR. A number on the bar comes apart again the
   next time somebody edits a margin, which is how this happened. There is one
   width now and one gutter, both here, and every container that decides the
   edge of the page reads them.

   WHY 1340 AND NOT 1180. Neither is invented: both were already in this file.
   1340 wins because the photograph is the thing everything is being aligned TO
   and it is not allowed to move, and because the alternative aligns the header
   with the sections and leaves it disagreeing with the photograph directly
   underneath it, which is the misalignment a person actually sees.

   WHAT THIS MOVES, and it is more than the header: every .wrap on the home page
   goes out by 80px on each side at wide viewports, so the trust bar, the story,
   the process and the footer now share one edge with the header and the hero.
   Leaving them at 1180 would have traded the header/hero mismatch for a
   footer/FAQ one. The v67 report enumerates every block that moved.

   MOBILE IS UNTOUCHED, and that is structural rather than careful: 1340 is
   wider than any phone, so the max-width never applies below it, and the
   padding under 860px is set by the media query further down exactly as it was.
   =========================================================================== */
:root{--page:1340px;--page-gutter:40px}

:root{--bg:#d8d6ce;--ink:#1f1c19;--soft:#625c56;--line:#c8c5bb;--accent:#7c7268;--accent2:#3a352f;--card:#e6e4dc;--g1:#cecbc1;--g2:#bcb8ab;--dark:#1f1c19;--darkfg:#d8d6ce;--darksoft:#9a948a;--darkline:#3a352f;--darkaccent:#b0a89b;--close1:#d2cfc6;--close2:#c4c0b4}
body{background:var(--bg);color:var(--ink);font-family:'Inter',sans-serif;line-height:1.6;-webkit-font-smoothing:antialiased}
a{text-decoration:none;color:inherit}

/* ===========================================================================
   A LINK IN RUNNING TEXT LOOKS LIKE A LINK
   ---------------------------------------------------------------------------
   v95 point 1. The reset directly above is right for the header, the buttons
   and the accessory cards: every one of those says what it is by its shape,
   and an underline on them would be noise. It is wrong for a link inside a
   sentence, where the shape IS the sentence. Measured before the rule below
   existed, with tools/v95-underlines.py: five links on this site sat in prose
   with neither an underline nor a colour of their own, so they were words in a
   paragraph and there was nothing to tell a reader to press them.

   THE UNDERLINE, AND NOT A COLOUR. --accent against --bg was settled
   elsewhere and is not reopened here, so these links keep exactly the colour
   the text around them already has and are marked by the line alone. That is
   also the one link cue that survives not being able to see colour.

   SCOPED BY SECTION, NOT BY A CLASS ON EACH ANCHOR. A class has to be
   remembered every time somebody writes a link, and the one nobody remembers
   is the one that stays invisible, which is the defect being fixed. The five
   section classes below are the body of the two marketing pages and appear on
   no other page in this repository: neither studio.html nor accessories.html
   carries any of them, which is why this rule cannot reach into the
   application by accident.

   `.story h2` is named on its own because the home page's one in-body link
   lives in a heading rather than a paragraph, and a link nobody can see is a
   link nobody can see whatever tag it sits in. `.foot .cr` is named on its own
   because the credit line is shared chrome and is meant to carry the underline
   on every page that shows it.

   WHAT IS DELIBERATELY NOT HERE, and none of it is reachable by these
   selectors: the header navigation, every .btn and .nav-cta, and any anchor
   that wraps a whole card. tools/v95-underlines.py counts those separately and
   reads 0 underlined in both the before and the after run.
   =========================================================================== */
:is(.intro,.story,.process,.trust,.faq-ans) :is(p,li) a,
.story h2 a,
.foot .cr a{
  text-decoration-line:underline;
  text-decoration-thickness:1px;
  /* Far enough off the baseline that the descenders in "page" and "Hero" are
     not struck through, which is what the browser default does at this size. */
  text-underline-offset:3px;
  text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);
  transition:text-decoration-color .2s,text-decoration-thickness .2s
}
/* Hover and focus both change, and neither of them changes a colour of the
   brand: the line goes from a tint of the text to the text's own colour and
   doubles in weight. It is a change in the mark, not in the word. */
:is(.intro,.story,.process,.trust,.faq-ans) :is(p,li) a:hover,
.story h2 a:hover,
.foot .cr a:hover,
:is(.intro,.story,.process,.trust,.faq-ans) :is(p,li) a:focus-visible,
.story h2 a:focus-visible,
.foot .cr a:focus-visible{
  text-decoration-color:currentColor;
  text-decoration-thickness:2px
}
/* And the keyboard keeps a ring of its own on top of that, so focus is never
   left relying on a two pixel difference in an underline to be found. This is
   the same 2px --accent outline the FAQ summaries and the review rail already
   use, so it is the one focus style on the site rather than a second one. */
:is(.intro,.story,.process,.trust,.faq-ans) :is(p,li) a:focus-visible,
.story h2 a:focus-visible,
.foot .cr a:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
  border-radius:3px
}
img{max-width:100%;display:block}
button{font-family:inherit;cursor:pointer;border:none;background:none}
.wrap{max-width:var(--page);margin:0 auto;padding:0 var(--page-gutter)}

/* nav */
/* The chrome names its own ink rather than inheriting the page's. It is one
   header and one footer wherever it appears, and accessories.html sets
   `color: var(--st-ink)` on the body, which is rgb(16,14,12) against this
   file's rgb(31,28,25). Everything else about the two matched to the pixel;
   the wordmark came out a shade darker on one page than the other. */
.nav,.foot{color:var(--ink)}
.nav{position:sticky;top:0;z-index:100;background:color-mix(in srgb,var(--bg) 88%,transparent);backdrop-filter:blur(14px);border-bottom:1px solid var(--line)}
.nav .in{max-width:var(--page);margin:0 auto;padding:16px var(--page-gutter);display:flex;align-items:center;justify-content:space-between}
.brand{display:inline-flex;align-items:center;gap:14px;cursor:pointer;line-height:1}
.brand .l-bar{width:4px;height:42px;background:var(--accent);flex-shrink:0}
.brand .txt{font-family:'Fraunces',serif;font-weight:600;font-size:34px;letter-spacing:-0.025em;line-height:1}
.brand .txt .d{color:var(--accent)}
/* no cart in the header any more, so the links sit at the right edge themselves */
.nav .links{display:flex;gap:36px;font-size:15.5px;color:var(--soft);margin-left:auto;margin-right:0}
.nav .links a{cursor:pointer;transition:color .2s;font-weight:600}
.nav .links a:hover{color:var(--ink)}
/* the one thing in the header anybody is meant to click, so it is a control
   rather than another word in a row of words */
.nav .links a.nav-cta{background:var(--ink);color:var(--bg);padding:9px 20px;border-radius:100px;font-weight:600;transition:transform .2s,background .2s,color .2s}
.nav .links a.nav-cta:hover{color:var(--bg);background:var(--accent);transform:translateY(-1px)}
/* The second pill. Same size, same shape, same place in the row, and one
   step down the hierarchy the site already has: .btn.ghost is an outline of
   the filled button, and this is an outline of the filled pill. The
   configurator stays the loudest thing in the header. */
.nav .links a.nav-cta.nav-cta-2{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--line)}
.nav .links a.nav-cta.nav-cta-2:hover{background:var(--ink);color:var(--bg);box-shadow:inset 0 0 0 1.5px var(--ink)}
.nav .links{align-items:center}

/* The phone menu button and the scrim behind the open panel. Both are off on
   the desktop, where the links are a row in the header and nothing overlays. */
.nav-burger{display:none}
.nav-scrim{display:none}

/* image placeholder */
.frame{position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;color:var(--soft);background:linear-gradient(150deg,var(--g1),var(--g2))}
img.frame{width:100%;height:auto;object-fit:cover;display:block;background:none}
/* A picture is only a wrapper for choosing the file. Without this it becomes the grid
   item in .story .row and the box that lays out in .hero, in place of the img inside it,
   which is not what any of the rules below are written against. */
picture{display:contents}
/* And the source has to go with it. Taking the picture out of the layout hands ALL of
   its children to the parent, not just the img, and a bare <source> computes to inline
   in the browser, not to none. So every <source> came back as a second, zero-height
   item in .story .row's grid and ate a cell, which pushed the img on to a row of its
   own underneath the text. Hiding it is what makes display:contents mean "the img is
   the item". It does not affect which file is chosen: the picture element picks its
   source from the DOM, not from the box tree. */
source{display:none}

/* hero side by side */
.wrap-hero{max-width:var(--page);margin:0 auto;padding:0 var(--page-gutter)}
.hero{position:relative;width:100%;min-height:540px;display:flex;align-items:flex-end;padding-bottom:52px;overflow:hidden;border-radius:18px;margin-top:20px;box-shadow:0 40px 80px -20px rgba(31,28,25,.42),0 10px 30px rgba(31,28,25,.18)}
.hero-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
.hero-overlay{position:absolute;inset:0;z-index:1;background:linear-gradient(90deg,rgba(20,18,16,0.62) 0%,rgba(20,18,16,0.4) 34%,rgba(20,18,16,0.14) 62%,rgba(20,18,16,0.03) 100%),linear-gradient(0deg,rgba(20,18,16,0.55) 0%,rgba(20,18,16,0.25) 34%,rgba(20,18,16,0) 60%)}
.hero-content{position:relative;z-index:2;color:#fff;text-align:left;width:100%;padding:0 60px}
.hero-content .inner{max-width:54%}
.hero-content .hero-line{font-family:'Fraunces',serif;font-weight:340;font-size:clamp(44px,6vw,82px);line-height:1.0;letter-spacing:-0.02em;margin-bottom:22px;color:#fff;white-space:nowrap}
.hero-content .hero-line em{font-style:italic;font-weight:340;color:#e8d9c4}
.hero-btn{background:#fff;color:var(--ink);padding:15px 38px;font-weight:600}
.hero-btn:hover{background:var(--ink);color:#fff}
.btn{display:inline-block;background:var(--ink);color:var(--bg);padding:15px 32px;border-radius:100px;font-size:15px;font-weight:500;transition:transform .2s,background .2s;cursor:pointer}
.btn:hover{transform:translateY(-2px)}
.btn.ghost{background:transparent;color:var(--ink);border:1px solid var(--ink)}
.btn.ghost:hover{background:var(--ink);color:var(--bg)}

/* trust */
.trust{border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:26px 0}
.trust .in{display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap;list-style:none}
.trust .t{font-size:13px;color:var(--soft)}
.trust .t b{color:var(--ink);font-weight:600}

/* intro */
.intro{padding:64px 0 0;text-align:center;max-width:720px;margin:0 auto}
.intro .k{font-size:12px;letter-spacing:0.2em;text-transform:uppercase;color:var(--accent2);margin-bottom:20px;font-weight:600}
.intro h1,.intro h2{font-family:'Fraunces',serif;font-weight:300;font-size:clamp(30px,3.6vw,42px);line-height:1.2;letter-spacing:-0.02em;margin-bottom:22px}
/* v79 point 4. THE HOME'S h1 IS TWO DELIBERATE LINES NOW, so the first of them
   has to fit on one line or the break produces an orphan instead of a pair:
   "We don't make desk / shelves. / We make Yours." with "shelves." alone.

   MEASURED IN BOTH FACES, WHICH IS THE PART THAT MATTERS HERE. This site loads
   its fonts with `font-display: optional`, so a first visit that does not win
   the race renders in the fallback for the whole of its life, and the fallback
   is wider. At 30px the sentence is 359px in Fraunces and 361px in Georgia,
   against a 346px box at 390 and 349px at 393: it wraps in both. At 26px it is
   312px and 313px, which fits both with about 33px to spare.

   Only below 420px, because at 430 the box is 386px and 30px already fits in
   either face with 25px of room. Scoped away from .wsh-intro, which shares
   .intro and is a different page with a different heading. */
@media (max-width:420px){
  .intro:not(.wsh-intro) h1{font-size:26px}
}
.intro p{font-size:17px;color:var(--soft);line-height:1.85}

/* story */
.story{padding:90px 0}
.story .row{display:grid;grid-template-columns:1fr 1fr;gap:70px;align-items:center;margin-bottom:80px}
.story .row:last-child{margin-bottom:0}
.story .row:nth-child(even) .txt{order:2}
.story .frame{aspect-ratio:4/3;border-radius:14px;box-shadow:0 40px 80px -20px rgba(31,28,25,.42),0 10px 30px rgba(31,28,25,.18)}
.story img.frame{aspect-ratio:auto;height:auto}
.story .k{font-size:12px;letter-spacing:0.2em;text-transform:uppercase;color:var(--accent);margin-bottom:16px;font-weight:600}
.story h1,.story h2{font-family:'Fraunces',serif;font-weight:400;font-size:34px;line-height:1.15;letter-spacing:-0.02em;margin-bottom:18px}
.story p{font-size:16px;color:var(--soft);line-height:1.8;margin-bottom:14px}

/* process */
.process{background:var(--dark);color:var(--darkfg);padding:90px 0}
.process .k{font-size:12px;letter-spacing:0.2em;text-transform:uppercase;color:var(--darkaccent);margin-bottom:16px;font-weight:600;text-align:center}
.process h2{font-family:'Fraunces',serif;font-weight:300;font-size:42px;text-align:center;margin-bottom:56px;letter-spacing:-0.02em}
.process .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:44px}
.process .steps-4{grid-template-columns:repeat(4,1fr);gap:32px}
/* The number and the title share a line, and the paragraph runs full width
   under both. It was a centred hexagon with the title beneath it, which cost a
   row of height in each of the four columns and read as two separate things.
   The phone has been laid out this way since v47; this is the same shape at
   desktop sizes. */
/* `align-content: start` matters. The four steps are grid items in a row, so
   each one stretches to the tallest, and a grid's auto rows stretch with it:
   the hexagon row grew by a different amount in each column depending on how
   long that column's paragraph was, and the four numbers sat at four different
   heights. Packing the rows to the top makes the first row exactly the hexagon
   in all four, so the paragraphs start on one line. */
.process .st{text-align:left;display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:15px;align-items:center;align-content:start}
.process .st .hex{width:58px;height:64px;margin:0;grid-row:1;position:relative;display:flex;align-items:center;justify-content:center}
.process .st .hex::before{content:"";position:absolute;inset:0;background:var(--darkaccent);opacity:.16;clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)}
.process .st .hex::after{content:"";position:absolute;inset:1.5px;background:var(--dark);clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)}
.process .st .hex span{position:relative;z-index:1;font-family:'Fraunces',serif;font-size:16px;color:var(--darkaccent);letter-spacing:0.06em}
.process .st h3{font-family:'Fraunces',serif;font-weight:500;font-size:20px;margin:0;grid-row:1;line-height:1.2}
.process .st p{font-size:14px;color:var(--darksoft);line-height:1.75;grid-column:1 / -1;margin-top:12px}
.process-cta{text-align:center;margin-top:56px}
.process-btn{background:var(--bg);color:var(--ink);padding:15px 38px;font-weight:600}
.process-btn:hover{background:var(--darkaccent);color:var(--ink)}

/* ==================== THE WORKSPACE HERO PAGE ====================
   v72 point 2, and it is four rules because the page is built entirely out of
   boxes this stylesheet already had: .intro, .story, .process and .faq. A
   landing page that needed its own layout would be a landing page that drifts
   away from the site the first time anything here changes. These only give it
   the breathing room a page with no photograph at the top needs. */
.wsh-intro{padding:80px 0 0;max-width:820px}
.wsh-intro h1{margin-bottom:22px}
.wsh-cta{margin-top:34px}
.wsh-note{padding:88px 0 8px}


/* ==================== WHAT OUR CUSTOMERS SAY ====================
   v73 point 4. The only hard part is that the texts are different lengths and
   that must not read as a mistake.

   THE GRID DOES IT, NOT A CLAMP ON THE TEXT. Grid items stretch to the tallest
   in the row by default, so all four cards are the same height without anyone
   measuring anything; inside each card the caption is pushed to the bottom
   with `margin-top:auto`, so the four names sit on one line whatever the
   quotes above them do. Nothing is truncated: every word the customer wrote is
   on the page.

   THE STARS ARE AN SVG, not a character. A text star is whatever the reader's
   font decides it is, it can arrive as an emoji on one platform and a hollow
   outline on another, and this site loads its fonts from a third party that
   can be slow. A path is the same shape everywhere and it is 5 of them, so
   "five stars" is countable rather than asserted. The row carries the reading
   as one aria-label and each star is aria-hidden, so a screen reader says it
   once. */
.revs{padding:56px 0 0}
.revs .k{font-size:12px;letter-spacing:0.2em;text-transform:uppercase;color:var(--accent2);margin-bottom:22px;font-weight:600;text-align:center}
.rev-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:18px}
.rev{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:22px 22px 20px;display:flex;flex-direction:column}
.stars{display:flex;gap:3px;margin-bottom:14px}
.stars svg{width:15px;height:15px;fill:var(--accent);flex-shrink:0}
.rev blockquote{font-size:14px;line-height:1.7;color:var(--ink);margin-bottom:18px}
/* The caption is pushed down rather than placed, which is what keeps the four
   names on one line when the quotes above them are four different lengths. */
.rev figcaption{margin-top:auto;padding-top:14px;border-top:1px solid var(--line);display:flex;flex-direction:column;gap:2px}
.rev figcaption b{font-size:14px;font-weight:600;color:var(--ink)}
.rev-when{font-size:12.5px;color:var(--soft)}
.rev-src{font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--accent);font-weight:600}
/* Two across before they get cramped, and one across on a phone, further
   down in the narrow block with everything else that changes there. */
@media (max-width:1080px){
.rev-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
}

/* ---- v76 point 2: what happens when there are more than fit ---------------
   NOT ONE RULE ABOVE THIS LINE CHANGED, and that is the design. Everything
   here is behind `:has(.rev:nth-child(5))`, so with four cards or fewer the
   stylesheet the browser applies is the one that was there before this pass
   and the section cannot have moved. The proof is a pixel comparison rather
   than an argument, but the argument is why the comparison could come out at
   zero: there is nothing for it to compare.

   THE FIFTH CARD IS THE SWITCH. Nobody sets a flag, nothing counts anything,
   and no width in here is written per card: `grid-auto-columns` says how wide
   ONE column is, and the browser makes as many as there are children. Adding a
   review is adding a <figure class="rev">.

   EVERY REVIEW IS IN THE SERVED HTML, ALWAYS. This is a stylesheet. There is
   no script, nothing is fetched, and nothing is hidden: the sixth review is in
   the response `curl` gets whether or not anybody scrolls to it. Text that is
   not in the served HTML does not exist to a search engine, and the whole
   value of these is their text.

   THE SCROLLBAR APPEARS ONLY WHEN IT IS DOING SOMETHING. With four there is
   no overflow, so there is no bar to be ugly. From five there is, and it is
   the thin one the rest of the site already uses, in the palette, with room
   made under the cards so it never sits on top of them.

   REACHABLE THREE WAYS. A finger drags it. A trackpad or shift with a wheel
   moves it. And the container carries role="group" and tabindex="0" in the
   markup, so it is a stop in the tab order and the arrow keys walk it, which
   is what a scrollable region owes somebody who does not use a pointer.
   Snapping is `proximity`, not `mandatory`: mandatory fights a reader who is
   halfway between two cards on purpose. */
.rev-grid:has(.rev:nth-child(5)){
  grid-template-columns:none;
  grid-auto-flow:column;
  grid-auto-columns:calc((100% - 54px) / 4);
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
  padding-bottom:14px;
  scrollbar-width:thin;
  scrollbar-color:var(--line) transparent;
}
.rev-grid:has(.rev:nth-child(5)) .rev{scroll-snap-align:start}
.rev-grid:has(.rev:nth-child(5))::-webkit-scrollbar{height:8px}
.rev-grid:has(.rev:nth-child(5))::-webkit-scrollbar-track{background:transparent}
.rev-grid:has(.rev:nth-child(5))::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.rev-grid:has(.rev:nth-child(5))::-webkit-scrollbar-thumb:hover{background:var(--accent)}
.rev-grid:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:4px}
@media (max-width:1080px){
  .rev-grid:has(.rev:nth-child(5)){grid-auto-columns:calc((100% - 16px) / 2)}
}

/* ==================== FAQ ====================
   Cards, per FAQ_style.md. Still native <details> and <summary>: the opening
   and closing needs no script, the summary is already a control in the tab
   order, and find-in-page can still reach a closed answer. The script below
   only closes the others, and the page is fully usable without it.

   The expansion is the 0fr to 1fr grid-rows trick, which animates to the
   content's own height without anybody having to measure it. */
.faq{padding:96px 0 100px;border-top:1px solid var(--line)}
.faq-head{max-width:640px;margin:0 auto 44px;text-align:center}
.faq-head .k{font-size:12px;letter-spacing:0.2em;text-transform:uppercase;color:var(--accent2);margin-bottom:16px;font-weight:600}
.faq-head h2{font-family:'Fraunces',serif;font-weight:300;font-size:clamp(30px,3.6vw,42px);line-height:1.2;letter-spacing:-0.02em}

.faq-list{display:flex;flex-direction:column;gap:14px;max-width:780px;margin:0 auto}
.faq-item{background:var(--card);border:1px solid transparent;border-radius:16px;transition:border-color .25s,box-shadow .3s,background .25s;overflow:hidden}
.faq-item[open]{border-color:var(--line);box-shadow:0 18px 40px -22px rgba(31,28,25,.4);background:color-mix(in srgb,var(--card) 70%,#fff)}
.faq-item summary{list-style:none;cursor:pointer;padding:22px 24px;display:flex;align-items:center;justify-content:space-between;gap:20px;font-family:'Fraunces',serif;font-weight:400;font-size:19px;letter-spacing:-.01em;color:var(--ink);transition:color .2s}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item:hover summary{color:var(--accent)}
.faq-item summary:focus-visible{outline:2px solid var(--accent);outline-offset:-4px;border-radius:16px}
.faq-mk{flex-shrink:0;width:30px;height:30px;border-radius:50%;border:1.5px solid var(--accent);position:relative;transition:transform .35s cubic-bezier(.4,0,.2,1),background .25s}
.faq-mk::before,.faq-mk::after{content:"";position:absolute;background:var(--accent);border-radius:2px;transition:background .25s}
.faq-mk::before{width:12px;height:1.5px;top:50%;left:50%;transform:translate(-50%,-50%)}
.faq-mk::after{height:12px;width:1.5px;top:50%;left:50%;transform:translate(-50%,-50%);transition:opacity .35s,transform .35s}
.faq-item[open] .faq-mk{transform:rotate(135deg);background:var(--accent)}
.faq-item[open] .faq-mk::before,.faq-item[open] .faq-mk::after{background:#fff}
.faq-item[open] .faq-mk::after{opacity:0}
.faq-ans{overflow:hidden;display:grid;grid-template-rows:0fr;transition:grid-template-rows .38s cubic-bezier(.4,0,.2,1)}
.faq-item[open] .faq-ans{grid-template-rows:1fr}
.faq-ans-inner{overflow:hidden;min-height:0}
/* Closing is the half the browser does not animate: it hides the content the
   moment `open` comes off. The script holds it open, adds this class to run the
   same transition backwards, and drops `open` when it finishes. Declared after
   the [open] rule so it wins at equal specificity. */
.faq-item.is-closing .faq-ans{grid-template-rows:0fr}
.faq-item.is-closing{box-shadow:none}
.faq-ans p{padding:0 24px 24px;color:var(--soft);font-size:15.5px;line-height:1.8;max-width:60ch}

@media (prefers-reduced-motion:reduce){
.faq-item,.faq-mk,.faq-ans,.faq-mk::before,.faq-mk::after{transition:none}
}
@media (max-width:860px){
.faq{padding:64px 0 72px}
.faq-item summary{font-size:17px;padding:19px 18px;gap:14px}
.faq-ans p{padding:0 18px 20px;font-size:15px}
}

/* footer */
/* the line that closes the page. --line is nearly the same value as --bg, so at
   1px it disappeared: this is the same greige family, mixed dark enough to read. */
.foot{padding:16px 0 30px;border-top:2px solid color-mix(in srgb,var(--ink) 34%,var(--bg))}
.foot .in{display:flex;justify-content:space-between;gap:30px;flex-wrap:wrap;margin-bottom:18px}
.foot .brand{margin-bottom:10px}
.foot .brand .l-bar{height:36px}
.foot .brand .txt{font-size:29px}
.foot .about{font-size:13px;color:var(--soft);max-width:34ch;line-height:1.7}
/* A place name is one thing and the browser must not break it in half. At 390px
   the legal line ended "... commercial license. Austin," and put "TX." alone on
   a line of its own.

   `text-wrap: pretty` is the whole fix, and it is the fix because of what the
   text is: nothing follows "TX.", so the only way the browser can separate it
   from "Austin," is by leaving it alone on the last line, which is precisely
   the orphan this property exists to prevent. The same is true of "Texas." in
   the line above it.

   It was a `<span class="nb">` with `white-space: nowrap` first. That worked
   too and cost 175 pixels of the DESKTOP footer: an inline box boundary splits
   the text into two runs and the glyphs after it round to different subpixels,
   so the line said the same words in the same place and rasterised differently.
   Measured, not guessed: with the span in place and the nowrap rule switched
   off, the same 175 pixels still differed. No element, no difference. */
.foot .about,.foot .cr span{text-wrap:pretty}
.foot .col{text-align:right}
.foot .col h2{font-size:12px;letter-spacing:0.12em;text-transform:uppercase;color:var(--soft);margin-bottom:14px}
.foot .col a{display:block;font-size:14px;color:var(--ink);margin-bottom:9px;cursor:pointer}
/* v75. NO RULE ABOVE THIS ROW, and less air around it.

   The footer already has one line, its own 2px top border, which is what
   separates it from the page. This row had a second one, and a footer divided
   into two panels is a footer that reads as two things. It is one thing: who
   made this and who designed it.

   The padding that went with it was there to hold the rule off the text. With
   no rule there is nothing to hold off, so it comes down to the gap the two
   blocks actually need. Measured on the four pages that carry this footer:
   329.52px tall at 1440 before, 559.13px at 390.

   order-confirmed.html and 404.html carry their own one line footers and never
   had a second rule, so there was nothing on them to take away. */
.foot .cr{font-size:12px;color:var(--soft);padding-top:10px;display:flex;justify-content:space-between;align-items:flex-end;flex-wrap:wrap;gap:12px}
.foot .cr span:last-child{text-align:right;line-height:1.6}

@media (max-width:860px){
.nav .links{display:none}
/* The hero is one photograph with the copy laid over it, so on a narrow screen
   the only thing that matters is how wide the copy column is allowed to be.
   `.hero-content` keeps a 60px inset and `.inner` a 54% cap, both of which are
   desktop numbers, and until this block set them the sum was
   390 - 80 - 120 = 190, times 54%, or a 103px column: the heading broke into
   three lines, the sentence into seven, and the call to action wrapped into a
   circle. 22px is the padding `.wrap` already takes below, so the hero now
   lines up with every other section instead of sitting further in than all of
   them. */
.wrap-hero{padding:0 14px}
.hero-content{padding:0 26px}
.hero-content .inner{max-width:100%}
/* nowrap is a desktop measure. 390px cannot hold the line at 44px, so let it break. */
.hero-content .hero-line{white-space:normal}
.wsh-intro{padding-top:56px}
.wsh-note{padding:60px 0 4px}
.revs{padding:44px 0 0}
.rev-grid{grid-template-columns:1fr;gap:14px}
/* v76. One per view, with the next one peeking so there is a reason to
   push. Only from the fifth card: with four they stack the way they do. */
.rev-grid:has(.rev:nth-child(5)){grid-auto-columns:calc(100% - 34px)}
.story .row{grid-template-columns:1fr;gap:36px}
.story .row:nth-child(even) .txt{order:0}
.process .steps{grid-template-columns:1fr;gap:36px}
.wrap,.nav .in{padding:0 22px}
.nav .in{padding:14px 22px}
}

/* ==================== SHIPPING & RETURNS MODAL ==================== */
.modal-ov{position:fixed;inset:0;z-index:1000;background:rgba(20,18,16,0.55);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;padding:24px;opacity:0;pointer-events:none;transition:opacity .28s ease}
.modal-ov.on{opacity:1;pointer-events:auto}
.modal{position:relative;background:var(--bg);border-radius:18px;max-width:540px;width:100%;max-height:85vh;overflow-y:auto;padding:40px 40px 36px;box-shadow:0 40px 90px -20px rgba(20,18,16,.5);transform:translateY(14px) scale(.98);transition:transform .28s cubic-bezier(.2,.8,.2,1)}
.modal-ov.on .modal{transform:translateY(0) scale(1)}
.modal-x{position:absolute;top:18px;right:20px;width:34px;height:34px;border-radius:50%;background:transparent;border:none;font-size:26px;line-height:1;color:var(--soft);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .2s,color .2s}
.modal-x:hover{background:var(--line);color:var(--ink)}
.modal h3{font-family:'Fraunces',serif;font-weight:400;font-size:28px;letter-spacing:-0.02em;margin-bottom:22px;padding-right:30px}
.modal-body h4{font-family:'Fraunces',serif;font-weight:500;font-size:17px;margin:20px 0 8px;color:var(--ink)}
.modal-body h4:first-child{margin-top:0}
.modal-body p{font-size:15px;color:var(--soft);line-height:1.7;margin-bottom:4px}
.modal-body a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}
.modal-body a:hover{color:var(--ink)}


/* ===========================================================================
   THE HOME PAGE ON A PHONE
   ---------------------------------------------------------------------------
   Everything below is inside a media query and scoped to `.home`, which is on
   the body of index.html only. Both halves of that matter: the query keeps the
   desktop untouched, and the scope keeps this off studio.html, accessories.html
   and 404.html, which share this stylesheet.

   ONE VALUE FOR THE VERTICAL RHYTHM. `--sec` is the distance between the
   content of one section and the content of the next, and every section takes
   half of it above and half below. Sections that are filled, the trust strip
   and the dark process band, keep their half inside the fill, which is where it
   belongs: the edge of a filled band is the boundary, so the whitespace outside
   it plus the padding inside it is the gap a reader actually sees. Before this
   the same gap was six different numbers between 78px and 180px.
   =========================================================================== */
@media (max-width: 860px) {

body{--sec:56px;--sec-half:28px}

/* ---- 1. the menu, in the strip the logo is already in --------------------
   The button sits in `.nav .in`, which is the flex row holding the wordmark,
   so it lands at the right end of that same strip rather than starting a
   second row under it. The panel it opens is the desktop `<nav class="links">`
   itself, laid out as a column and dropped below the header. */
.nav .in{position:relative}
.nav-burger{display:flex;flex-direction:column;justify-content:center;align-items:center;
  gap:5px;width:44px;height:44px;margin:0 -10px 0 auto;border-radius:10px;flex-shrink:0}
.nav-burger span{display:block;width:22px;height:2px;background:var(--ink);border-radius:2px;
  transition:transform .26s cubic-bezier(.4,0,.2,1),opacity .18s}
/* open: the top and bottom bars cross, the middle one goes */
.nav.is-open .nav-burger span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav.is-open .nav-burger span:nth-child(2){opacity:0}
.nav.is-open .nav-burger span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
.nav-burger:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.nav .links{display:flex;flex-direction:column;align-items:stretch;gap:8px;
  position:absolute;top:100%;left:0;right:0;z-index:2;
  background:var(--bg);border-bottom:1px solid var(--line);
  padding:14px 22px 20px;margin:0;
  box-shadow:0 26px 44px -26px rgba(31,28,25,.55);
  opacity:0;visibility:hidden;transform:translateY(-10px);
  transition:opacity .24s ease,transform .24s cubic-bezier(.4,0,.2,1),visibility .24s}
.nav.is-open .links{opacity:1;visibility:visible;transform:none}
/* Every row is a 46px control, which is what makes them thumb sized. */
.nav .links a{display:flex;align-items:center;min-height:46px;padding:0 6px;
  font-size:16px;font-weight:600;color:var(--ink);border-radius:10px}
/* The two pills keep their own colours. The rule above sets a colour at the
   same specificity and comes first, so without these the filled pill was ink
   on ink and its label vanished. */
.nav .links a.nav-cta{justify-content:center;padding:0 20px;min-height:48px;font-size:15.5px;color:var(--bg)}
.nav .links a.nav-cta.nav-cta-2{color:var(--ink)}
.nav .links a:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

.nav-scrim{display:block;position:fixed;inset:0;z-index:90;
  background:rgba(20,18,16,.42);opacity:0;pointer-events:none;transition:opacity .24s ease}
.nav-scrim.on{opacity:1;pointer-events:auto}

/* ---- 2. the hero, cropped wide ------------------------------------------
   Same file, same bytes: this only changes the shape of the box the photograph
   is cropped into. At 540px tall in a 346px column the box was 0.64:1, and
   object-fit:cover then showed a 27% wide vertical slice of a 2.35:1
   photograph, which is a strip of dowel and no product. */
.home .hero{min-height:0;aspect-ratio:16/9;padding-bottom:var(--sec-half);margin-top:14px;border-radius:14px}
.home .hero-content{padding:0 22px}
.home .hero-content .hero-line{font-size:34px;margin-bottom:13px;line-height:1.05}
/* THE CALL TO ACTION HAS TO READ AS A CONTROL, WHICH ON THIS CROP IT DID NOT.
   Nothing about the button's own rules differs between the two widths: same
   fill, same label colour, same weight, same 15px Inter, same 100px radius,
   and the label measures 11.65:1 on its own fill at both. What differs is the
   photograph underneath it. On the desktop the pill sits at 80% of the hero's
   height, over desk shadow that reads rgb(67,60,54), so the dark fill still
   separates from its ground at 1.57:1. The 16:9 crop moves it to 60% of a much
   shorter box, where the ground runs from rgb(14,13,16) to rgb(91,84,69): the
   median is DARKER than the fill, at 1.10:1, so the left half of the pill
   disappeared into near black while the right half showed against lit dowel.
   An edge that exists along part of a shape and not the rest does not read as
   a button at all.

   So the fill is inverted here and only here. White on this photograph is at
   least 7:1 against the lightest thing under it, which is what a primary call
   to action on an image should be, and it is what `.hero-btn` was written to
   be before `.btn` overrode it on source order. The desktop keeps the dark
   pill exactly as it is: this rule is inside the query. */
.home .hero-btn{min-height:44px;padding:0 20px;display:inline-flex;align-items:center;
  font-size:14px;font-weight:600;background:var(--bg);color:var(--ink);
  box-shadow:0 6px 18px -8px rgba(20,18,16,.55)}
/* The copy sits bottom left over the crop, so the floor of the gradient is
   lifted to keep it legible against the lit part of the photograph. */
.home .hero-overlay{background:
  linear-gradient(0deg,rgba(20,18,16,.80) 0%,rgba(20,18,16,.62) 34%,rgba(20,18,16,.30) 62%,rgba(20,18,16,.04) 88%,rgba(20,18,16,0) 100%),
  linear-gradient(90deg,rgba(20,18,16,.52) 0%,rgba(20,18,16,.24) 55%,rgba(20,18,16,0) 100%)}

/* ---- 3. the trust strip, one claim per line ----------------------------- */
.home .trust{padding:var(--sec-half) 0}
.home .trust .in{display:flex;flex-direction:column;align-items:flex-start;gap:10px;flex-wrap:nowrap}
.home .trust .t{font-size:13.5px;line-height:1.45;position:relative;padding-left:16px;text-align:left}
.home .trust .t::before{content:"";position:absolute;left:0;top:.58em;width:5px;height:5px;
  border-radius:50%;background:var(--accent)}

/* ---- 7. one gap everywhere ---------------------------------------------- */
.home .intro{padding:var(--sec-half) 0}
.home .story{padding:var(--sec-half) 0}
.home .story .row{margin-bottom:var(--sec);gap:26px}
.home .process{padding:var(--sec-half) 0}
.home .faq{padding:var(--sec-half) 0}
.foot{padding-top:var(--sec-half)}

/* ---- 4. the step number and its title on one line ----------------------- */
.home .process .steps{gap:30px}
.home .process h2{font-size:30px;margin-bottom:30px}
.home .process .st{text-align:left;display:grid;grid-template-columns:auto 1fr;
  column-gap:13px;align-items:center}
.home .process .st .hex{width:46px;height:51px;margin:0;grid-row:1}
.home .process .st .hex span{font-size:14px}
.home .process .st h3{margin:0;grid-row:1;font-size:19px;line-height:1.2}
.home .process .st p{grid-column:1 / -1;margin-top:9px}
.home .process-cta{margin-top:30px}

/* ---- 5 and 6. the two footer alignments --------------------------------- */
.foot .in{flex-direction:column;gap:24px;margin-bottom:18px}
/* 5. the links column reads from the left on a phone. It is right aligned on
      the desktop and stays that way; this rule is inside the query. */
.foot .col{text-align:left}
.foot .col a{min-height:44px;display:flex;align-items:center;margin-bottom:0}

/* ---- every tappable thing at 44px or more ------------------------------
   The wordmark is a link back to the home page in both places, the modal's
   close button was a 33px circle, and the footer links were text with a line
   height. None of them was a comfortable thumb. The inline email address in
   the Shipping and Returns copy is left alone on purpose: it sits inside a
   sentence, which is the case WCAG 2.5.8 exempts, and padding it to 44px
   would open a hole in the paragraph. */
.nav .brand{min-height:44px}
.foot .brand{min-height:44px;margin-bottom:6px}
.modal-x{width:44px;height:44px;top:14px;right:14px}
/* 6. the three legal lines all sit against the right edge. */
.foot .cr{flex-direction:column;align-items:flex-end;text-align:right;gap:6px;padding-top:8px}
.foot .cr span,.foot .cr span:last-child{text-align:right}

}

/* ===========================================================================
   THE PHONE MENU WITH MOTION TURNED OFF
   ---------------------------------------------------------------------------
   Last in the file and matching the specificity of the block above on purpose.
   Written inside the reduced-motion query further up it lost, because the block
   above comes later at equal weight, and the transitions stayed on for exactly
   the readers who had asked for them to be off. Caught by reading the computed
   transition-duration rather than by watching the panel.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
.nav .links,.nav-burger span,.nav-scrim{transition:none}
}
