/* ==========================================================================
   Storefront additions.

   site.css is the design as drawn. This file adds only what a real store needs
   and the static mock-up never had: a working navigation drawer, bag and
   checkout layouts, form controls, and the small state messages that come from
   a server rather than from a designer's imagination.
   ========================================================================== */

:root {
  --pi-paper: #f7f6f1;
  --pi-ink: #20211d;
  --pi-muted: #686b62;
  --pi-line: #deded4;
  --pi-orange: #e8753f;
  /* Mirrors the .wrap gutter so a full-bleed strip can cancel it exactly. */
  --pi-gutter: 5vw;
}

@media (max-width: 460px) {
  :root {
    --pi-gutter: 4.5vw;
  }
}

/* --------------------------------------------------------------- utilities */

.pi-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.pi-crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pi-muted);
  padding: 22px 0 0;
}

.pi-crumbs a:hover {
  color: var(--pi-ink);
}

.pi-resultcount {
  font-size: 12px;
  color: var(--pi-muted);
  margin: 0 0 18px;
}

/* --------------------------------------------------- collection pages */

.pi-lede {
  max-width: 56ch;
  margin: 14px 0 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--pi-muted);
}

/* The tile is a fixed shape, so the lede has to be clamped rather than
   allowed to push one card taller than its neighbours. Two lines is enough
   to tell a visitor whether this collection is their problem. */
.category {
  justify-content: flex-start;
  gap: 6px;
}

.category .cat-count {
  margin-top: auto;
}

.category .cat-lede {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  /* Three lines, clamped by CSS rather than sliced in the template: the old
     character cut left sentences dangling ("the hook that"). */
  -webkit-line-clamp: 3;
  overflow: hidden;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--pi-muted);
}

/* The collection's own copy sits under the grid, in the same editorial frame
   the product page uses for its full description. */
.pi-collection-story {
  margin-top: 8px;
}

/* A collection with one or two products left a hole the width of the missing
   third card. Two products fill a row; one product would rather be a wide
   card than a lonely square. */
.grid--products[data-count="2"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid--products[data-count="1"] {
  grid-template-columns: minmax(0, 520px);
}

/* ------------------------------------------------------------------- nav */

.navbtn {
  border: 0;
  background: transparent;
  font-size: 12px;
  padding: 6px 2px;
  min-height: 0;
}

.navbtn:hover {
  opacity: 0.62;
}

/* The bag is an icon now, so the count needs its own anchor: a number floating
   next to a tote reads as a price unless it is boxed. */
.navbag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 2px;
  text-decoration: none;
}

.navbag:hover {
  opacity: 0.62;
  text-decoration: none;
}

.navbag__count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--pi-ink);
  color: var(--pi-paper);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* An empty bag does not need a badge saying "0". */
.navbag.is-empty .navbag__count {
  display: none;
}

/* Hover has to survive the trip from the trigger down to the sheet. The
   trigger is a 20px word inside a 76px bar, so without this there is a 40px
   band of header belonging to neither element: move the pointer down slowly
   and it leaves the drop, the sheet starts to fade, and the menu feels
   broken. Stretching both the row and each drop to the bar's full height
   closes that gap with geometry instead of with a delay. */
.navlinks {
  align-items: center;
  align-self: stretch;
}

/* A menu is one word, not a two-line paragraph. Without this a label as short
   as "Trouble check" folds in half as soon as the bar gets tight, which reads
   as a broken header; the overflow is measured by script instead and the
   drawer takes over before anything has to wrap.
   Top-level items only: the panel's own links inherit from here otherwise, and
   a one-line rule turns their descriptions into text that runs over the next
   column. */
.navlinks > a.navlink,
.navlinks > .navdrop > a.navlink,
.logo {
  white-space: nowrap;
}

.navdrop {
  align-self: stretch;
}

/* ----------------------------------------------------- nav: the menu sheet */

/* The second level hangs off its own trigger and drops straight down, the way
   a menu is expected to. Two things make that work:
     1. `.navdrop` is positioned, so left:0 is the word's left edge rather than
        the window's, and the panel is as wide as its contents (fit-content).
     2. `.navdrop` also stretches to the full height of the bar
        (`align-self:stretch` on `.navlinks`), so top:100% is the header's
        bottom edge — the pointer travelling down never leaves the menu and
        never falls into a gap that closes it.
   A menu pinned to the left edge of the page reads as a second header bar; one
   that starts under the word you hovered reads as a menu.
   `max-width` keeps the widest menu inside the window; the left offset is
   trimmed in script for the last items in the bar (see app.js `fitDrop`). */
.navdrop {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.navdrop__toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.pi-icon--chev {
  opacity: 0.5;
  transition: transform 0.18s ease;
}

.navdrop:hover .pi-icon--chev,
.navdrop:focus-within .pi-icon--chev,
.navdrop.is-open .pi-icon--chev {
  transform: rotate(180deg);
}

.navdrop__panel {
  /* The bar is upper-case micro type; a menu is reading, not labelling.
     Everything inside resets, and the labels that want caps (eyebrow, column
     heading, the "see everything" link) ask for them again. */
  text-transform: none;
  font-size: 13px;
  letter-spacing: normal;
  position: absolute;
  left: 0;
  right: auto;
  /* max-content, not fit-content: with the panel resolving against a ~60px
     menu word, shrink-to-fit measures "available width" against that word and
     squashes the columns to nothing. max-content asks the content instead, and
     max-width is the only cap that matters. */
  width: max-content;
  max-width: calc(100vw - 24px);
  top: 100%;
  z-index: 90;
  max-height: calc(100vh - 96px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* `fitDrop()` overrides the ceiling above with the room that is actually
     left, but a menu that has to scroll should say so: the thin bar is the
     only hint that "$20+" is not the end of the list. */
  scrollbar-width: thin;
  scrollbar-color: rgba(32, 33, 29, 0.28) transparent;
  background: var(--pi-white);
  /* All four edges now: the panel used to sit against the window's left edge,
     where only a right and bottom rule were needed to read as a sheet. Hung
     under its trigger it floats, and a card with two ruled sides looks like it
     lost one. The sides stay hairline; the foot keeps the heavier rule so the
     panel still ends like a printed page. */
  border-left: 1px solid var(--pi-line);
  border-right: 1px solid var(--pi-line);
  border-bottom: 1px solid var(--pi-ink);
  box-shadow: 0 26px 60px rgba(20, 21, 18, 0.13);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s linear 0.16s;
}

.navdrop:hover .navdrop__panel,
.navdrop:focus-within .navdrop__panel,
.navdrop.is-open .navdrop__panel {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s;
}

/* Rail + columns. The rail is the magazine contents page: what this section
   is, one sentence about it, and the way to the whole thing. The rail is a
   fixed 244px so the rule between it and the columns lands on the same
   vertical line in every menu — with a shrink-to-fit panel a max-width alone
   would let one menu's rail be as narrow as its sentence.
   The padding is in pixels, not vw: the panel is no longer a window-wide
   sheet, so viewport-relative padding would eat a fifth of a 700px menu. */
.navdrop__inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: 26px 28px 28px;
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 26px;
}

.navdrop__rail {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding-right: 20px;
  border-right: 1px solid var(--pi-line);
}

.navdrop__eyebrow {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--pi-orange);
}

.navdrop__note {
  margin: 0;
  max-width: 24ch;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 17px;
  line-height: 1.32;
  letter-spacing: -0.025em;
  color: var(--pi-ink);
}

.navdrop__all {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--pi-ink);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--pi-ink);
}

.navdrop__all span {
  color: var(--pi-orange);
}

.navdrop__all:hover {
  opacity: 1;
  color: var(--pi-orange);
}

/* Each heading starts a column, and the number of tracks comes from the
   markup (`--tracks`), because the panel is as wide as its contents: this is
   the one number that decides how wide the menu is. Tracks are fixed and equal
   rather than content-sized, so the panel's right edge lands in the same place
   whether the descriptions are long or short. Below 1220px they turn fluid —
   see the rail's breakpoint at the end of this file.
   208px, not 272: the panel centres under its trigger, and a 920px menu under
   a word near the left edge has nowhere to centre — it just gets clamped flat
   against the window edge, which is the look this whole change is fixing.
   208 is what four columns cost: 4 × 208 + 3 × 24 = 904px of columns, 1130
   with the rail, 1186 with the panel's own padding — inside the 1240 ceiling
   with room to spare. The old 226 was sized for three columns, where a long
   heading ("If you would rather browse") had to stay on one line. */
.navdrop__cols {
  --track: 208px;
  --gap: 24px;
  display: grid;
  grid-template-columns: repeat(var(--tracks, 2), var(--track));
  align-content: start;
  column-gap: var(--gap);
  row-gap: 28px;
}

.navdrop__col {
  position: relative;
  min-width: 0;
}

/* A rule down the seam between two columns, drawn inside the gap so it costs
   the columns no width. Two columns of seven and three items leave a large
   quiet area under the short one; with the seam ruled, that area reads as the
   short column's own margin rather than as a hole in the sheet, and the panel
   reads as a contents page instead of as a list that ran out. The markup says
   which columns are seams (see navDrop): a column that starts a grid row has
   none. */
.navdrop__col--seam::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--gap, 32px) / -2);
  width: 1px;
  background: var(--pi-line);
}

/* A heading-less group was counted as two tracks; it has to claim them, or the
   second track stays empty and the sheet keeps its wasted right-hand margin. */
.navdrop__col--plain {
  grid-column: span 2;
}

.navdrop__head {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin: 0 0 10px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--pi-line);
  font-family: inherit;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.15em;
  line-height: 1.2;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.navdrop__head i {
  font-style: normal;
  color: var(--pi-orange);
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}

/* A column that is wide gets two rows inside it; a narrow one gets a list.
   auto-fill, not auto-fit: the empty tracks should collapse rather than leave
   a link stranded in a column of its own. */
.navdrop__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(186px, 1fr));
  gap: 6px 22px;
}

/* A panel with no headings at all (the collections list) is four entries and
   nothing else. Four across reads as a strip of fragments; two by two reads
   as a list someone wrote. */
.navdrop__col--plain .navdrop__list {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  max-width: 660px;
}

.navdrop__item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 9px 0;
}

.navdrop__itemlabel {
  font-size: 13px;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--pi-ink);
}

.navdrop__desc {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--pi-muted);
}

/* site.css dims every hovered link in a nav; inside the sheet the label is
   already turning orange, and dimming it too reads as disabled. */
.navdrop__item:hover {
  opacity: 1;
}

.navdrop__item:hover .navdrop__itemlabel {
  color: var(--pi-orange);
}

/* ------------------------------------------------- nav: the bar's own marks */

.navlink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* The one item the shop would point a lost visitor at, marked with the same
   star used in the logo — a mark, not a button. */
.navlink__mark {
  font-style: normal;
  font-size: 9px;
  line-height: 1;
  color: var(--pi-orange);
  transform: translateY(-1px);
}

.navlink--accent:hover {
  opacity: 1;
  color: var(--pi-orange);
}

.navlinks a[aria-current='page'] {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}

/* The drawer's version of the same emphasises: orange, and the star stays. */
.mobile-nav a.is-accent,
.mobile-nav__text.is-accent,
.mobile-nav__group > summary.is-accent {
  color: var(--pi-orange);
}

/* The logo and the menu button sit in one flex row so the toggle can be
   placed to the *left* of the wordmark on phones without moving the logo off
   centre or reordering the DOM on desktop. */
.navleft {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.menu {
  /* site.css shows the word "Menu" from 760px down; here it becomes an icon,
     so the padding and border are reset and the hit area stays 44px. */
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: -11px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--pi-ink);
  min-height: 0;
}

.menu:hover {
  background: rgba(32, 33, 29, 0.06);
}

.pi-icon {
  display: block;
}

/* A left-hand drawer: the toggle is on the left, so the panel it opens comes
   from the left. A top-down sheet under a left-hand button read as a
   disconnect and covered the page's own headline. */
.mobile-nav {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 120;
  width: min(340px, 88vw);
  height: 100%;
  overflow-y: auto;
  background: var(--pi-paper);
  border-right: 1px solid var(--pi-line);
  padding: 20px 24px 30px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-shadow: 26px 0 60px rgba(20, 21, 18, 0.16);
  animation: pi-slide 0.22s ease-out;
}

/* Without a scrim the drawer's edge cut straight into the page and looked
   like a broken section rather than an overlay. */
.pi-menu-scrim {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: rgba(24, 25, 22, 0.42);
  border: 0;
  padding: 0;
  animation: pi-fade 0.2s ease-out;
}

.pi-menu-scrim[hidden] {
  display: none;
}

@keyframes pi-slide {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: none;
  }
}

@keyframes pi-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.mobile-nav[hidden] {
  display: none;
}

.mobile-nav a {
  padding: 15px 0;
  border-bottom: 1px solid var(--pi-line);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 21px;
  letter-spacing: -0.03em;
}

.mobile-nav__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}

/* Pinned to the bottom: without it the drawer was 60% empty paper on a tall
   phone, which read as a loading state rather than a finished menu. */
.mobile-nav__foot {
  margin-top: auto;
  padding-top: 28px;
  border-top: 1px solid var(--pi-line);
}

.mobile-nav__foot p {
  margin: 0 0 10px;
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: 0.04em;
  color: var(--pi-muted);
}

.mobile-nav__foot a {
  display: inline;
  padding: 0;
  border: 0;
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pi-ink);
  border-bottom: 1px solid var(--pi-line);
}

.mobile-nav__close {
  display: grid;
  place-items: center;
  border: 1px solid var(--pi-line);
  background: transparent;
  width: 40px;
  height: 40px;
  min-height: 0;
}

.mobile-nav__close:hover {
  background: rgba(32, 33, 29, 0.06);
}

/* Second level inside the drawer. The layout itself is defined further down
   with the rest of the drawer rules; only the divider belongs here, because
   the parent link has to give up its own rule when a sub-list follows it. */
.mobile-nav > a:has(+ .mobile-nav__sub) {
  border-bottom: 0;
  padding-bottom: 4px;
}

body.pi-nav-open {
  overflow: hidden;
}

/* The bar fits the wordmark and four menus on one line down to about 900px.
   Below that the wordmark broke in two lines and the last menu wrapped, which
   reads as a broken page rather than as a small screen — so the drawer takes
   the bar's place from here, not from 760px.

   That number is only right for four menus. Add two and the bar needs the
   drawer at 1024; add four and it needs it at 1280. A media query cannot know
   how many words the owner puts in the bar, so the width test below is the
   rule and this one is the floor: script measures the bar and sets
   `is-navcramped` when the links no longer fit at 900px or above. */
@media (max-width: 900px) {
  .menu {
    display: inline-flex;
  }

  .navlinks {
    display: none;
  }

  .nav {
    gap: 10px;
  }

  .navright {
    gap: 12px;
  }
}

/* Same collapse, decided by the content rather than by the window. */
body.is-navcramped .menu {
  display: inline-flex;
}

body.is-navcramped .navlinks {
  display: none;
}

body.is-navcramped .nav {
  gap: 10px;
}

body.is-navcramped .navright {
  gap: 12px;
}

/* At 320–360px the wordmark plus two text links is wider than the screen;
   the wordmark gives up a little weight before the links do. */
@media (max-width: 400px) {
  .logo {
    font-size: 20px;
    letter-spacing: -1px;
  }

  .navbtn {
    font-size: 11px;
  }
}

/* --------------------------------------------------------- added to bag */

/* The confirmation is a panel, not a redirect: the visitor keeps the page they
   were reading, sees what went into the bag and the running total, and decides
   whether to keep going or check out. */
.pi-added-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  /* flex-start + margin:auto on the panel: centred when it fits, scrollable
     from the top when a short landscape phone cannot show it all. */
  align-items: flex-start;
  justify-content: center;
  padding: clamp(12px, 4vw, 40px);
  background: rgba(24, 25, 22, 0.52);
  overflow-y: auto;
  animation: pi-fade 0.16s ease-out;
}

.pi-added-backdrop[hidden] {
  display: none !important;
}

.pi-added {
  position: relative;
  width: min(440px, 100%);
  margin: auto;
  background: var(--pi-paper);
  color: var(--pi-ink);
  border: 1px solid var(--pi-line);
  padding: 30px clamp(22px, 4vw, 34px) 26px;
  box-shadow: 0 26px 70px rgba(20, 21, 18, 0.26);
  animation: pi-rise 0.22s ease-out;
}

@keyframes pi-rise {
  from {
    transform: translateY(14px);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

.pi-added-close {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  color: var(--pi-ink);
  min-height: 0;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.pi-added-close:hover {
  background: rgba(32, 33, 29, 0.06);
  border-color: var(--pi-line);
}

.pi-added .eyebrow {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-right: 40px;
}

.pi-added h2 {
  font-size: clamp(30px, 4vw, 36px);
  line-height: 1.02;
  letter-spacing: -0.045em;
  margin: 10px 0 20px;
}

.pi-added h2 em {
  font-style: italic;
}

.pi-added-item {
  display: flex;
  gap: 14px;
  align-items: center;
  border-top: 1px solid var(--pi-line);
  border-bottom: 1px solid var(--pi-line);
  padding: 16px 0;
}

.pi-added-visual {
  width: 66px;
  height: 66px;
  flex: 0 0 66px;
  background: #e7e4da;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.pi-added-visual img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pi-added-visual .shape {
  font-size: 28px;
  color: #3b4138;
}

.pi-added-copy {
  min-width: 0;
  display: grid;
  gap: 6px;
}

.pi-added-name {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 19px;
  line-height: 1.2;
  letter-spacing: -0.03em;
  border-bottom: 1px solid transparent;
  justify-self: start;
  text-align: left;
}

.pi-added-name:hover {
  border-bottom-color: var(--pi-ink);
}

.pi-added-meta {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-added-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  padding: 16px 0 4px;
  font-size: 13px;
  color: var(--pi-muted);
}

.pi-added-row strong {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 20px;
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--pi-ink);
}

.pi-added-note {
  margin: 4px 0 0;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-added-note[hidden] {
  display: none;
}

.pi-added-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 20px;
}

.pi-added-actions .btn {
  padding: 14px 12px;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  white-space: nowrap;
}

.pi-added-fine {
  margin: 14px 0 0;
  font-size: 10.5px;
  line-height: 1.6;
  color: var(--pi-muted);
  letter-spacing: 0.02em;
}

@media (max-width: 480px) {
  .pi-added {
    padding: 26px 20px 22px;
  }

  .pi-added-actions {
    grid-template-columns: 1fr;
  }

  .pi-added-actions .btn {
    padding: 15px 12px;
  }
}

/* ------------------------------------------------------------- bag panel */

/* Slides from the right, the side the bag button lives on. Same paper and rule
   weight as the rest of the shop — it should read as the page folding open,
   not as a widget dropped on top of it. */
.pi-bag-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  justify-content: flex-end;
  background: rgba(24, 25, 22, 0.52);
  animation: pi-fade 0.16s ease-out;
}

.pi-bag-backdrop[hidden] {
  display: none !important;
}

.pi-bag {
  width: min(404px, 100%);
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--pi-paper);
  color: var(--pi-ink);
  border-left: 1px solid var(--pi-line);
  box-shadow: -26px 0 70px rgba(20, 21, 18, 0.22);
  animation: pi-slide-in 0.24s ease-out;
}

@keyframes pi-slide-in {
  from {
    transform: translateX(100%);
  }
  to {
    transform: none;
  }
}

.pi-bag-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  padding: 24px 22px 18px;
  border-bottom: 1px solid var(--pi-line);
}

.pi-bag-head h2 {
  font-size: 32px;
  line-height: 1;
  letter-spacing: -0.045em;
  margin: 8px 0 0;
}

.pi-bag-head h2 em {
  font-style: italic;
}

.pi-bag-close {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  padding: 0;
  border: 1px solid var(--pi-line);
  background: transparent;
  color: var(--pi-ink);
  min-height: 0;
  transition: background 0.15s ease;
}

.pi-bag-close:hover {
  background: rgba(32, 33, 29, 0.06);
}

.pi-bag-lines {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 2px 22px;
  -webkit-overflow-scrolling: touch;
}

.pi-bag-line {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--pi-line);
}

.pi-bag-line.is-soldout {
  opacity: 0.62;
}

.pi-bag-thumb {
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  background: #e7e4da;
  overflow: hidden;
}

.pi-bag-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pi-bag-thumb .shape {
  font-size: 24px;
  color: #3b4138;
}

.pi-bag-info {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.pi-bag-info a {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 16px;
  line-height: 1.25;
  letter-spacing: -0.02em;
  border-bottom: 1px solid transparent;
  justify-self: start;
}

.pi-bag-info a:hover {
  border-bottom-color: var(--pi-ink);
}

.pi-bag-info span {
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-bag-line strong {
  font-size: 13px;
  font-weight: 400;
  white-space: nowrap;
}

.pi-bag-loading,
.pi-bag-empty p {
  margin: 22px 0;
  font-size: 13px;
  line-height: 1.7;
  color: var(--pi-muted);
}

.pi-bag-empty {
  display: grid;
  gap: 4px;
  justify-items: start;
  align-content: center;
  min-height: 100%;
  padding-bottom: 40px;
}

.pi-bag-foot {
  padding: 18px 22px 22px;
  border-top: 1px solid var(--pi-line);
  background: var(--pi-paper);
}

.pi-bag-foot[hidden] {
  display: none;
}

.pi-bag-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-bag-row strong {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 23px;
  font-weight: 400;
  letter-spacing: -0.03em;
  color: var(--pi-ink);
  text-transform: none;
}

.pi-bag-note {
  margin: 6px 0 0;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-bag-ship {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 0;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--pi-muted);
}

.pi-bag-actions {
  display: grid;
  gap: 8px;
  margin-top: 16px;
}

.pi-bag-actions .btn {
  padding: 14px 12px;
  font-size: 10.5px;
  letter-spacing: 0.1em;
}

.pi-bag-fine {
  margin: 12px 0 0;
  font-size: 10.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}



/* --------------------------------------------------------------- product */

.product-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-img .shape {
  line-height: 1;
}

.cat-count {
  font-size: 11px;
  color: var(--pi-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.product .price s {
  color: var(--pi-muted);
  font-size: 12px;
  margin-right: 4px;
}

/* ---------------------------------------------------------- product page */

.pi-media {
  display: block;
}

.detailimg {
  position: relative;
  overflow: hidden;
  background: var(--pi-soft, #efefe7);
}

.detailimg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 1 / 1;
  display: block;
}

/* The whole main image is the zoom target. Reset the button to invisible so
   the photo still looks like a photo, but the cursor promises more. */
.pi-zoombtn {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}

.pi-zoombtn:focus-visible {
  outline: 3px solid var(--pi-orange);
  outline-offset: -3px;
}

/* A remote URL that 404s or refuses hotlinking. Say so, in words, on the page
   the owner is looking at — silence is what made this feel broken. */
.pi-broken {
  position: absolute;
  inset: auto 0 0 0;
  padding: 10px 14px;
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(32, 33, 29, 0.86);
}

.detailimg img.is-broken {
  opacity: 0;
}

.detail-glyph {
  font-family: Georgia, serif;
  font-size: clamp(90px, 14vw, 160px);
  line-height: 1;
  color: var(--orange);
}

.pi-gallery {
  display: grid;
  /* Column count comes from the number of slides, capped at four. Three slides
     in a four-column grid leave a hole that reads as a missing image; ten
     slides in a five-column grid leave two orphans. */
  grid-template-columns: repeat(var(--pi-thumbs, 4), minmax(0, 1fr));
  gap: 8px;
  margin-top: 8px;
}

.pi-thumb {
  padding: 0;
  border: 1px solid transparent;
  background: var(--pi-soft, #efefe7);
  cursor: pointer;
  line-height: 0;
  transition: border-color 0.18s ease, opacity 0.18s ease;
}

.pi-thumb img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
}

.pi-thumb:hover {
  border-color: var(--pi-ink);
}

.pi-thumb.is-active {
  border-color: var(--pi-orange);
  box-shadow: 0 0 0 1px var(--pi-orange);
}

.pi-thumb:focus-visible {
  outline: 3px solid var(--pi-orange);
  outline-offset: 2px;
}

/* A dead thumb keeps its square, greyed, with a diagonal mark: the owner needs
   to count slides and spot the bad one, not wonder where they went. */
.pi-thumb.is-broken {
  border-color: #c2554a;
  border-style: dashed;
  background: repeating-linear-gradient(
    135deg,
    #f4ece9 0 6px,
    #efe3df 6px 12px
  );
}

.pi-thumb.is-broken img {
  opacity: 0;
}

/* ------------------------------------------------------------------ lightbox */

html.pi-locked {
  overflow: hidden;
}

.pi-lightbox {
  position: fixed;
  inset: 0;
  /* Above the header (100). The header carries a positive z-index of its own so
     the nav dropdown can clear the page content, and a full-screen image viewer
     that leaves the nav sitting on top of it is not full-screen. */
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 4vmin;
  background: rgba(16, 17, 14, 0.965);
  animation: pi-fade 0.18s ease;
}

.pi-lightbox-figure {
  margin: 0;
  max-width: min(1100px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
}

.pi-lightbox img {
  max-width: 100%;
  max-height: 82vh;
  object-fit: contain;
  background: #fff;
}

.pi-lightbox figcaption {
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
  letter-spacing: 0.08em;
}

.pi-lightbox-close,
.pi-lightbox-nav {
  position: absolute;
  border: 1px solid rgba(255, 255, 255, 0.24);
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.18s ease;
}

.pi-lightbox-close:hover,
.pi-lightbox-nav:hover {
  background: rgba(255, 255, 255, 0.18);
}

.pi-lightbox-close {
  top: 18px;
  right: 18px;
  width: 42px;
  height: 42px;
  font-size: 24px;
  line-height: 1;
}

.pi-lightbox-nav {
  top: 50%;
  transform: translateY(-50%);
  width: 46px;
  height: 64px;
  font-size: 18px;
}

.pi-lightbox-nav.prev {
  left: 10px;
}

.pi-lightbox-nav.next {
  right: 10px;
}

@keyframes pi-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pi-lightbox {
    animation: none;
  }
}

.qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--pi-line);
  background: transparent;
}

.qty button {
  border: 0;
  background: transparent;
  padding: 12px 15px;
  font-size: 16px;
  line-height: 1;
  min-height: 0;
}

.qty-input {
  width: 52px;
  text-align: center;
  border: 0 !important;
  background: transparent !important;
  min-height: 0 !important;
  -moz-appearance: textfield;
  appearance: textfield;
  padding: 0;
}

.qty-input::-webkit-outer-spin-button,
.qty-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.buyrow {
  align-items: stretch;
  /* Quantity plus two buttons will not share one line at 390px without
     shrinking to unreadable, so the second button takes its own row. */
  flex-wrap: wrap;
}

.buyrow .btn--paynow {
  flex: 1 1 100%;
  min-height: 48px;
}

/* PayPal's own yellow. The palette here is warm paper, ink and orange, and
   this is the one element allowed to break it — a PayPal button that does not
   look like a PayPal button is worse than no express checkout at all. */
.buyrow .btn--paypal {
  background: #ffc439;
  border-color: #ffc439;
  color: #003087;
  padding-block: 12px;
}

.buyrow .btn--paypal:hover,
.buyrow .btn--paypal:focus-visible {
  background: #f2b52f;
  border-color: #f2b52f;
  color: #003087;
}

.pi-pp {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  line-height: 1;
}

/* Two overlapping italic P's. Drawn as letters rather than paths because at
   20px a path bowl closes up into a blob, while a letter keeps its counter. */
.pi-pp__mark {
  position: relative;
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
}

.pi-pp__mark i {
  position: absolute;
  font-style: italic;
  font-weight: 800;
  font-size: 21px;
  line-height: 1;
  letter-spacing: -0.06em;
}

.pi-pp__mark i:first-child {
  left: 0;
  top: 3px;
  color: #003087;
}

.pi-pp__mark i:last-child {
  left: 7px;
  top: 0;
  color: #009cde;
}

.pi-pp__word {
  font-size: 16.5px;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.03em;
  text-transform: none;
}

.pi-pp__word b {
  color: #003087;
  font-weight: inherit;
}

.pi-pp__word em {
  color: #009cde;
  font-style: inherit;
}

.pi-buyhint {
  margin: -12px 0 12px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--pi-muted);
}

.pi-alert--buy {
  margin: 18px 0 14px;
}

/* The delivery form on an order page sits where the address block would be,
   so it borrows the checkout's field styling rather than inventing another. */
.pi-orderform {
  margin-top: 4px;
  max-width: 460px;
}

/* The hint doubles as the error line, so it needs room under it either way. */
.pi-orderform .pi-hint {
  margin: 2px 0 18px;
}

.pi-orderform .btn {
  margin-top: 4px;
}

.pi-shipnote {
  font-size: 11.5px;
  color: var(--pi-muted);
  margin: 2px 0 0;
}

.pi-outofstock {
  border: 1px solid var(--pi-line);
  padding: 16px 18px;
  font-size: 13px;
  margin: 24px 0;
}

/* ------------------------------------------------------------ variant picker */

/* Values are chips, not a <select>: on a phone a native dropdown hides every
   other option behind a tap, and the whole point of a variant is comparison. */
.pi-options {
  margin: 26px 0 4px;
  display: grid;
  gap: 16px;
}

.pi-option__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}

.pi-option__name {
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-option__head b {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0;
}

.pi-option__values {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pi-option__value {
  border: 1px solid var(--pi-line);
  background: transparent;
  color: var(--pi-ink);
  padding: 0 16px;
  min-height: 42px;
  font-size: 12.5px;
  letter-spacing: 0;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.pi-option__value:hover:not(:disabled) {
  border-color: var(--pi-ink);
}

.pi-option__value.is-active {
  background: var(--pi-ink);
  border-color: var(--pi-ink);
  color: var(--pi-paper);
}

/* A crossed-out value says "this combination exists but is sold out"; hiding
   it would make the row of chips jump every time stock changed. */
.pi-option__value:disabled {
  color: #b3b4ab;
  border-style: dashed;
  cursor: not-allowed;
  text-decoration: line-through;
  background: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 4px,
    rgba(32, 33, 29, 0.045) 4px,
    rgba(32, 33, 29, 0.045) 8px
  );
}

/* ---------------------------------------------------- full description */

/* Body copy used to live in the right-hand column of .detail, which gave it
   ~330px of measure and a 64px h2. It gets its own full-width section now:
   sticky section index on the left, a readable column on the right. */
.pi-story {
  position: relative;
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  padding-block: clamp(44px, 6vw, 76px);
}

/* A border on .wrap would run the full element width, which is 2 x the gutter
   wider than every other rule on the page. Draw it inside the gutters instead. */
.pi-story::before {
  content: '';
  position: absolute;
  top: 0;
  left: var(--pi-gutter);
  right: var(--pi-gutter);
  height: 1px;
  background: var(--pi-line);
}

.pi-story-aside {
  position: sticky;
  top: 24px;
  align-self: start;
}

.pi-story-index {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  border-left: 1px solid var(--pi-line);
}

.pi-story-index a {
  display: block;
  margin-left: -1px;
  padding: 6px 0 6px 14px;
  border-left: 1px solid transparent;
  font-size: 12px;
  line-height: 1.45;
  color: var(--pi-muted);
  transition: color 0.15s ease, border-color 0.15s ease;
}

.pi-story-index a:hover {
  color: var(--pi-ink);
  border-left-color: var(--pi-orange);
}

.pi-story-note {
  margin: 22px 0 0;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-story-note a {
  color: var(--pi-ink);
  border-bottom: 1px solid var(--pi-line);
}

.pi-story-note a:hover {
  border-color: var(--pi-orange);
}

.pi-story-body {
  max-width: 660px;
  font-size: 15.5px;
  line-height: 1.78;
  color: #55584f;
}

.pi-story-body > :first-child {
  margin-top: 0;
}

.pi-story-body p {
  margin: 0 0 18px;
}

.pi-story-body h2 {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-size: clamp(25px, 2.4vw, 34px);
  line-height: 1.12;
  letter-spacing: -0.035em;
  color: var(--pi-ink);
  margin: 44px 0 12px;
  scroll-margin-top: 30px;
}

.pi-story-body h3 {
  font-size: 15px;
  letter-spacing: 0.01em;
  color: var(--pi-ink);
  margin: 28px 0 8px;
}

/* An H1 typed into body copy renders at the page's own title size unless it is
   caught here, and a 100px headline in the middle of an article turns the page
   into a poster. In the body it acts as the top section heading instead. */
.pi-story-body h1 {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 500;
  font-size: clamp(28px, 2.7vw, 38px);
  line-height: 1.12;
  letter-spacing: -0.035em;
  color: var(--pi-ink);
  margin: 40px 0 12px;
}

/* Four and five are support ranks, not sections: H3 already reads as a label,
   so H4 goes heavier and H5 becomes a caps tag. Without these two rules the
   browser's defaults (16px and 13px, both bold) make H4 look like body text
   and H5 look like a mistake. */
.pi-story-body h4 {
  font-size: 14px;
  font-weight: 600;
  color: var(--pi-ink);
  margin: 24px 0 6px;
}

.pi-story-body h5 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: rgba(32, 33, 29, 0.62);
  margin: 20px 0 6px;
}

/* The number above each heading is the same one the index uses; it makes the
   headings feel like sections of a file rather than bold text. */
.pi-story-num {
  display: block;
  margin-bottom: 7px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--pi-orange);
}

.pi-story-body strong {
  color: var(--pi-ink);
  font-weight: 600;
}

/* A paragraph that is entirely bold is a standfirst, not emphasis. */
.pi-story-body p.pi-story-lead {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(18px, 1.9vw, 22px);
  line-height: 1.5;
  letter-spacing: -0.02em;
  color: var(--pi-ink);
  margin-bottom: 26px;
}

.pi-story-body p.pi-story-lead strong {
  font-weight: 400;
}

.pi-story-body ul {
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
}

.pi-story-body ul li {
  position: relative;
  margin-bottom: 7px;
  padding-left: 18px;
}

.pi-story-body ul li::before {
  content: '✳';
  position: absolute;
  left: 0;
  top: 2px;
  font-size: 9px;
  color: var(--pi-orange);
}

.pi-story-body ol {
  margin: 0 0 22px;
  padding-left: 20px;
}

/* `尺寸：13.3 × 13.4 × 2.8 cm` reads as a spec, not a bullet. */
.pi-story-body li.pi-spec {
  display: grid;
  grid-template-columns: minmax(84px, 28%) minmax(0, 1fr);
  gap: 14px;
  margin: 0;
  padding: 10px 0;
  border-bottom: 1px solid var(--pi-line);
}

.pi-story-body ul li.pi-spec:first-child {
  border-top: 1px solid var(--pi-line);
}

.pi-story-body li.pi-spec::before {
  content: none;
}

.pi-spec-key {
  padding-top: 2px;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-spec-val {
  color: var(--pi-ink);
}

.pi-story-body blockquote {
  margin: 24px 0;
  padding-left: 18px;
  border-left: 2px solid var(--pi-orange);
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 19px;
  line-height: 1.5;
  color: var(--pi-ink);
}

.pi-story-body img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 22px 0;
}

.pi-story-body table {
  width: 100%;
  margin: 0 0 22px;
  border-collapse: collapse;
  font-size: 13.5px;
}

.pi-story-body th,
.pi-story-body td {
  padding: 9px 12px 9px 0;
  border-bottom: 1px solid var(--pi-line);
  text-align: left;
  vertical-align: top;
}

.pi-story-body th {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-story-body a {
  border-bottom: 1px solid var(--pi-line);
}

.pi-story-body a:hover {
  border-color: var(--pi-orange);
}

.pi-story-body code {
  padding: 1px 5px;
  background: var(--pi-soft, #ecebe2);
  font-size: 0.92em;
}

.pi-story-body hr {
  margin: 34px 0;
  border: 0;
  border-top: 1px solid var(--pi-line);
}

/* ------------------------------------------------------------------- bag */

.pi-cartpage {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 56px);
  align-items: start;
}

.pi-summary {
  border: 1px solid var(--pi-line);
  padding: clamp(20px, 3vw, 28px);
  background: var(--pi-white, #fffdf8);
  position: sticky;
  top: 24px;
}

.pi-summary .carttotal {
  margin: 0 0 12px;
  font-size: 14px;
}

.pi-summary .pi-total {
  border-top: 1px solid var(--pi-line);
  padding-top: 14px;
  margin-top: 16px;
  font-size: 18px;
}

.cartline form.qty {
  margin-top: 10px;
  border-color: var(--pi-line);
}

.cartline form.qty button {
  padding: 0 12px;
  min-height: 36px;
  font-size: 15px;
  line-height: 1;
  text-decoration: none;
}

.cartline form.qty span {
  min-width: 34px;
  text-align: center;
  font-size: 13px;
}

/* Scoped to the remove button. As `form button[type="submit"]` this also
   matched the quantity buttons and collapsed them to 6px wide. */
.pi-remove {
  border: 0;
  background: transparent;
  text-decoration: underline;
  font-size: 11px;
  padding: 6px 0;
  min-height: 0;
  margin-top: 4px;
  color: var(--pi-muted);
}

.pi-hint {
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--pi-muted);
  margin: 10px 0 0;
}

.pi-warn {
  color: #a5361c;
  font-size: 11px;
}

/* ------------------------------------------------------------ bag line rows */

/* A bag line now carries a picture, a variant name and a SKU. The old two
   columns put the price on whatever baseline the text happened to end at, so
   the money is pinned to the top of its own column instead. */
.pi-cartline__main {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  min-width: 0;
  flex: 1;
}

.pi-lineimg {
  flex: none;
  width: 76px;
  height: 76px;
  background: var(--pi-soft);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.pi-lineimg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pi-lineimg--glyph span {
  font-size: 28px;
  line-height: 1;
  color: #7c8172;
}

.pi-lineimg--sm {
  width: 56px;
  height: 56px;
}

.pi-lineimg--sm.pi-lineimg--glyph span {
  font-size: 21px;
}

/* The dashed tile matches the broken-image treatment elsewhere: an empty box
   with nothing in it reads as a slow-loading photo, not as "no photo". */
.pi-lineimg img.is-broken,
.pi-lineimg:has(img.is-broken) {
  background: repeating-linear-gradient(-45deg, var(--pi-soft), var(--pi-soft) 6px, #e6e5da 6px, #e6e5da 7px);
}

.pi-cartline__copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.pi-cartline__name {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.35;
}

a.pi-cartline__name:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.pi-cartline__meta {
  font-size: 11px;
  color: var(--pi-muted);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}

.pi-cartline__unit {
  font-size: 11.5px;
  color: var(--pi-muted);
  font-variant-numeric: tabular-nums;
}

.pi-cartline__side {
  flex: none;
  text-align: right;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.pi-cartline__total {
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

/* In the checkout summary the line is a mini-row, so it centres instead of
   top-aligning and loses the outer padding. */
.pi-summary__line {
  align-items: center;
  gap: 12px;
  padding: 14px 0;
  font-size: 13px;
}

.pi-summary__line:first-of-type {
  padding-top: 2px;
}

/* ------------------------------------------------------- checkout / forms */

.pi-checkout {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 56px);
  align-items: start;
}

.pi-formhead {
  font-size: 22px;
  font-family: Georgia, serif;
  letter-spacing: -0.03em;
  margin: 0 0 18px;
}

.pi-field {
  display: block;
  margin-bottom: 14px;
}

.pi-field label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
  margin-bottom: 6px;
}

.pi-field input,
.pi-field select {
  width: 100%;
  padding: 12px 14px;
  background: var(--pi-white, #fffdf8);
  border: 1px solid var(--pi-line);
  border-radius: 0;
  font-size: 15px;
  font-family: inherit;
  color: var(--pi-ink);
}

/* The native arrow is drawn by the OS and clashes with everything else on the
   page, so the select gets a hairline chevron of our own. `!important` is not
   laziness: site.css forces `background: … !important` on every select, which
   would otherwise wipe these four longhands out. */
.pi-field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 38px;
  background-image: linear-gradient(45deg, transparent 50%, var(--pi-muted) 50%),
    linear-gradient(135deg, var(--pi-muted) 50%, transparent 50%) !important;
  background-position: calc(100% - 20px) calc(50% + 1px), calc(100% - 15px) calc(50% + 1px) !important;
  background-size: 5px 5px, 5px 5px !important;
  background-repeat: no-repeat !important;
  cursor: pointer;
}

.pi-field select:disabled {
  color: var(--pi-muted);
  cursor: default;
}

/* `[hidden]` loses to any rule that gives the element a display value, and
   these two controls are swapped in place. */
.pi-field input[hidden],
.pi-field select[hidden] {
  display: none;
}

.pi-field input:focus,
.pi-field select:focus {
  outline: 2px solid var(--pi-ink);
  outline-offset: -1px;
}

.pi-searchpage {
  display: flex;
  gap: 10px;
  max-width: 620px;
  margin: 24px 0 0;
}

.pi-searchpage input {
  flex: 1;
  min-width: 0;
  padding: 13px 15px;
  border: 1px solid var(--pi-ink);
  background: var(--pi-white, #fffdf8);
  font-size: 16px;
}

/* ---------------------------------------------------------------- states */

.pi-alert {
  border-left: 3px solid var(--pi-orange);
  background: rgba(232, 117, 63, 0.08);
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.6;
  margin: 18px 0;
}

.pi-status {
  display: inline-block;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 1px solid var(--pi-line);
  padding: 8px 12px;
  margin: 6px 0 0;
}

.pi-status[data-status="paid"],
.pi-status[data-status="shipped"] {
  background: var(--pi-ink);
  color: var(--pi-paper);
  border-color: var(--pi-ink);
}

/* --------------------------------------------------------------- article */

.pi-article .prose {
  max-width: 720px;
}

.pi-standfirst {
  font-size: 17px;
  line-height: 1.7;
  color: var(--pi-muted);
  max-width: 640px;
  margin: 22px 0 0;
}

.pi-cover {
  margin: 32px 0 8px;
  max-width: 900px;
}

.pi-cover img {
  width: 100%;
  aspect-ratio: 1.8;
  object-fit: cover;
}

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  margin: 22px 0;
}

.prose th,
.prose td {
  border-bottom: 1px solid var(--pi-line);
  padding: 10px 12px 10px 0;
  text-align: left;
  vertical-align: top;
}

.prose th {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
  font-weight: 600;
}

.prose > table {
  display: table;
  max-width: 100%;
}

@media (max-width: 700px) {
  .prose > table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
}

/* --- typographic polish -------------------------------------------------- */

/* Avoids a one-word last line ("Gardening shouldn't require a recovery /
   day."). Browsers without support simply ignore the declaration. */
.hero h1,
.pageintro h1,
.section-head h2,
.blogcard h3,
.product h3,
.prose h2,
.manifesto h2 {
  text-wrap: pretty;
}

/* ==========================================================================
   Mobile layer

   The desktop design is a wide editorial grid: 3 columns, 76px between
   sections, 27px serif headlines. Dropped into 390px three things break at
   once, and they are the reason the phone version feels off rather than
   merely small.

   1. Rhythm.  `.wrap` sets `padding: 0 5vw` and wins the cascade against
      `.section { padding: 76px 0 }`, so on a phone every section loses its
      top and bottom padding entirely. Sections end up touching: the last
      "Read the case file" link sits 4px *above* the next section's eyebrow.
      Fixing this one thing restores most of the page's calm.

   2. Measure.  A 27px serif headline in a 171px column wraps to five lines
      and the two cards beside it wrap to four, so the columns never line up.
      Sentence-length headings need a full-width column.

   3. Competition.  A product card splits 171px between title and price. The
      price is 85px of it, so the title gets 74px and the subtitle becomes a
      six-line grey ribbon. On a phone the price belongs under the title.

   Everything below is scoped to <=760px (with a 620 and a 480 step) so the
   desktop composition keeps the proportions it was designed with.
   ========================================================================== */

/* --- rhythm: give every section its vertical space back ------------------ */

@media (max-width: 760px) {
  .wrap.section {
    padding-top: 44px;
    padding-bottom: 44px;
  }

  .wrap.pageintro {
    padding-top: 26px;
    padding-bottom: 36px;
  }

  .wrap.detail {
    padding-top: 22px;
    padding-bottom: 44px;
  }

  .section-head {
    margin-bottom: 22px;
    gap: 14px;
  }
}

/* --- header -------------------------------------------------------------- */

/* The header has to sit above the page, not merely look like it does.
 *
 * site.css gives every <header> a backdrop-filter, which silently makes it a
 * stacking context with z-index:auto. A stacking context at auto does not win
 * against page content - it is painted in tree order along with any other
 * position:relative box, and the header comes first in the document. So the
 * product page's .detailimg (position:relative) and the sticky .pi-summary
 * painted straight over the open dropdown. The panel's own z-index:90 could
 * never help: it only competes inside the header's context.
 *
 * Lifting the header itself to a positive z-index moves its whole context above
 * every z-index:auto positioned block. 100 stays under the mobile drawer (120)
 * and its scrim (110), so the drawer still covers the header as it should. */
.nav {
  position: relative;
  z-index: 100;
}

@media (max-width: 760px) {
  .announcement {
    padding: 8px 4vw;
    font-size: 10px;
    letter-spacing: 0.01em;
    line-height: 1.45;
  }

  /* Two clauses that do not fit one line at 390px. Stack them deliberately
     rather than leaving "$50" stranded on a line of its own. */
  .announcement__pitch,
  .announcement__ship {
    display: block;
  }

  .announcement__ship {
    margin-top: 1px;
    opacity: 0.82;
  }

  /* The star was a separator between two sentences; stacked, it is debris. */
  .announcement .star {
    display: none;
  }

  .nav {
    height: 58px;
    padding: 0 4.5vw;
    gap: 8px;
  }

  .logo {
    font-size: 18px;
  }

  .navright {
    gap: 2px;
    font-size: 11.5px;
    letter-spacing: 0.02em;
  }

  /* A 12px label in a 26px box is a miss waiting to happen. */
  .navright .navbtn,
  .navright .menu {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 9px;
    font-size: 11.5px;
  }

  .navright > :last-child {
    padding-right: 0;
  }
}

@media (max-width: 460px) {
  .navbtn:first-child {
    display: none;
  }

  .wrap {
    padding: 0 4.5vw;
  }
}

/* --- hero ---------------------------------------------------------------- */

@media (max-width: 760px) {
  .hero {
    padding-top: 28px;
    padding-bottom: 32px;
    gap: 24px;
  }

  /* 15vw was 47px on a 390 screen inside a 7.6ch measure - four lines, one
     of them the single word "little". Open the measure, shrink the type. */
  .hero h1 {
    max-width: none;
    font-size: clamp(2rem, 9vw, 2.75rem);
    line-height: 1.04;
  }

  .hero > div:first-child > p,
  .hero__aside > p {
    margin-top: 14px;
    font-size: 15px;
    line-height: 1.62;
  }

  .hero .actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 22px;
  }

  .hero .actions .btn {
    padding: 13px 8px;
    font-size: 10.5px;
    letter-spacing: 0.06em;
  }

  .hero-art {
    min-height: 0;
    aspect-ratio: 4 / 3;
  }

  .art-note {
    top: 14px;
    left: 14px;
    font-size: 9.5px;
  }

  .art-caption {
    right: 14px;
    bottom: 38px;
    font-size: 10px;
  }

  .hero-art:after {
    left: 14px;
    bottom: 14px;
    font-size: 9px;
    letter-spacing: 0.12em;
  }
}

/* --- product cards ------------------------------------------------------- */

@media (max-width: 760px) {
  .product-info {
    display: block;
    padding: 10px 0 0;
  }

  .product-info h3,
  .product h3 {
    font-size: 14.5px;
    line-height: 1.35;
  }

  .product-info .price,
  .product .price {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-top: 5px;
    font-size: 13px;
    white-space: normal;
  }

  /* Two lines of subtitle keeps card heights level without hiding the pitch. */
  .product .sub {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-top: 4px;
    font-size: 11px;
    line-height: 1.5;
  }

  .tag {
    top: 9px;
    left: 9px;
    padding: 6px 8px;
    font-size: 9.5px;
  }
}

@media (max-width: 480px) {
  .grid {
    gap: 14px 10px;
  }
}

/* --- editorial grids: journal + standard --------------------------------- */

@media (max-width: 620px) {
  .grid--posts,
  .grid--standard {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }

  .grid--posts .blogcard h3,
  .grid--standard .blogcard h3 {
    font-size: 23px;
    line-height: 1.14;
    margin: 10px 0 8px;
  }

  .grid--posts .blogcard p,
  .grid--standard .blogcard p {
    font-size: 13.5px;
    line-height: 1.6;
  }

  .blogvisual {
    aspect-ratio: 2 / 1;
    margin-bottom: 14px;
    font-size: 56px;
  }

  .blogcard .textlink {
    display: inline-block;
    margin-top: 10px;
  }
}

/* --- category tiles ------------------------------------------------------ */

@media (max-width: 760px) {
  .category {
    position: relative;
    padding: 16px 16px 14px;
    min-height: 124px;
  }

  .category .symbol {
    font-size: 24px;
  }

  .category strong {
    font-size: 19px;
    line-height: 1.22;
    padding-right: 20px;
  }

  .category .cat-count {
    font-size: 10px;
  }

  /* Inline, the arrow wrapped alone onto a third line on some tiles and not
     others. Pin it to the corner so every tile ends the same way. */
  .category__go {
    display: none;
  }

  .category::after {
    content: "↗";
    position: absolute;
    right: 14px;
    bottom: 12px;
    font-size: 12px;
    line-height: 1;
    opacity: 0.55;
  }
}

/* --- product detail ------------------------------------------------------ */

@media (max-width: 760px) {
  .pi-crumbs {
    padding-top: 16px;
    font-size: 10.5px;
    letter-spacing: 0.06em;
  }  .detail {
    gap: 22px;
  }

  .detail h1 {
    font-size: clamp(1.9rem, 8.4vw, 2.5rem);
  }

  .detail .price {
    margin: 4px 0 10px;
    font-size: 21px;
  }

  .detail .price s {
    font-size: 14px;
  }

  .detail-values {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px 14px;
    margin: 22px 0 18px;
    padding: 18px 0;
  }

  .detail-value strong {
    font-size: 10px;
    letter-spacing: 0.08em;
  }

  .detail-value span {
    font-size: 11px;
  }

  .detailimg {
    min-height: 0;
    aspect-ratio: 1 / 1;
  }

  .pi-gallery {
    gap: 6px;
  }

  .pi-lightbox {
    padding: 12px;
  }

  .pi-lightbox img {
    max-height: 74vh;
  }

  .pi-lightbox-nav {
    width: 38px;
    height: 52px;
    top: auto;
    bottom: 16px;
    transform: none;
  }

  .pi-lightbox-nav.prev {
    left: 16px;
  }

  .pi-lightbox-nav.next {
    right: 16px;
  }

  .pi-lightbox-close {
    top: 10px;
    right: 10px;
    width: 38px;
    height: 38px;
  }

  .buyrow {
    gap: 10px;
  }

  .product-accordions .accord summary {
    min-height: 58px;
  }

  .accord-copy strong {
    font-size: 12.5px;
  }

  .accord-copy small {
    font-size: 10.5px;
  }

  .pi-story {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    padding-block: 38px;
  }

  .pi-story-aside {
    position: static;
    display: block;
    margin-bottom: 22px;
  }

  /* On a phone the note is a standfirst, not a sidebar caption: it sits on its
     own line under the label instead of trailing it into a cramped run-on. */
  .pi-story-note {
    margin-top: 7px;
  }

  /* The index is redundant on a phone: the body is two screens long and the
     headings sit right next to each other. */
  .pi-story-index {
    display: none;
  }

  .pi-story-body {
    max-width: none;
    font-size: 15px;
    line-height: 1.72;
  }

  .pi-story-body h2 {
    font-size: 24px;
    margin-top: 34px;
  }

  .pi-story-body li.pi-spec {
    grid-template-columns: minmax(0, 1fr);
    gap: 3px;
    padding: 11px 0;
  }

  .pi-spec-key {
    font-size: 10px;
  }

  .pi-shipnote {
    font-size: 12px;
    line-height: 1.6;
  }
}

/* --- long-form copy ------------------------------------------------------ */

@media (max-width: 760px) {
  .prose h2 {
    font-size: 25px;
    line-height: 1.18;
    margin: 30px 0 10px;
  }

  .prose h3 {
    font-size: 19px;
    line-height: 1.25;
    margin: 24px 0 8px;
  }

  .prose p,
  .prose li {
    font-size: 15.5px;
    line-height: 1.7;
  }

  .prose blockquote {
    font-size: 17px;
    line-height: 1.5;
  }

  .pi-standfirst {
    font-size: 15.5px;
    line-height: 1.65;
    margin-top: 16px;
  }

  .pi-cover {
    margin: 22px 0 6px;
  }
}

/* --- inner page intros and filters --------------------------------------- */

@media (max-width: 760px) {
  .pageintro h1 {
    font-size: clamp(1.9rem, 8.6vw, 2.5rem);
  }

  /* The intro already carries an h1; a second 38px serif heading right under
     it competes with it instead of supporting it. */
  .pageintro h2 {
    font-size: 25px;
    line-height: 1.16;
  }

  .pageintro > p,
  .pageintro .prose p {
    font-size: 15px;
    line-height: 1.65;
  }

  /* Four chips fit the row, the fifth fell to a line of its own. A bleed-to-
     edge scroll strip keeps one clean line at any width, and the chip peeking
     off the right edge is the affordance. */
  .filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 8px;
    margin: 20px 0 16px;
    margin-inline: calc(-1 * var(--pi-gutter));
    padding: 0 var(--pi-gutter) 4px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .filters::-webkit-scrollbar {
    display: none;
  }

  .filter {
    flex: 0 0 auto;
  }

  .pi-resultcount {
    margin-bottom: 14px;
  }
}

/* --- newsletter + footer ------------------------------------------------- */

@media (max-width: 520px) {
  .newsletter {
    padding: 38px 5vw;
    gap: 20px;
  }

  .newsletter h2 {
    font-size: 30px;
    line-height: 1.1;
  }

  .emailform {
    flex-direction: column;
    gap: 12px;
    max-width: none;
  }

  .emailform input,
  .emailform .btn {
    width: 100%;
  }
}

/* The old footer was a 2fr/1fr/1fr/1fr grid of <br>-joined links: the brand
   column was 2x wide but held 2x less, and the three link lists sat at three
   different baselines. Brand and links are now two blocks on one row, and the
   link columns are real stacks with one rhythm. */
.footer {
  background: var(--pi-ink);
  color: var(--pi-paper);
  padding: clamp(46px, 6vw, 74px) 5vw 22px;
}

.footerinner {
  max-width: 1240px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 2fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: start;
}

.footer .logo--footer {
  display: inline-block;
  font-size: clamp(28px, 3vw, 34px);
  letter-spacing: -1.6px;
  line-height: 1.1;
  color: var(--pi-paper);
}

.footer .logo--footer .star {
  color: var(--pi-orange);
}

.footerblurb {
  margin: 16px 0 0;
  max-width: 30ch;
  font-size: 13.5px;
  line-height: 1.75;
  color: #b9bbb0;
}

/* The column count is set inline by the server as --ft-cols. Three is the
   fallback so the rule still makes sense on its own. */
.footercols {
  display: grid;
  grid-template-columns: repeat(var(--ft-cols, 3), minmax(0, 1fr));
  gap: clamp(18px, 3vw, 44px);
  padding-top: 4px;
}

/* Five or more shelves. Beside the brand block each one would be about 115px
   wide at 1240px and every second label would wrap, so the brand moves above
   and the columns get the full measure. */
.footerinner--stack {
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(26px, 3vw, 36px);
}

.footercols--dense {
  gap: clamp(14px, 2.2vw, 28px);
}

.footercol {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.footer .footercol h4 {
  margin: 0 0 12px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #8d9084;
}

.footer .footercol a {
  width: fit-content;
  padding: 3px 0;
  font-size: 13px;
  line-height: 1.75;
  color: #e7e8de;
  text-decoration: none;
}

.footer .footercol a:hover {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 5px;
}

.footerbottom {
  max-width: 1240px;
  margin: clamp(30px, 4vw, 48px) auto 0;
  padding-top: 18px;
  border-top: 1px solid #3b3e35;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: #9fa197;
}

.footerbottom__tag {
  white-space: nowrap;
}

@media (max-width: 900px) {
  .footerinner {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }

  .footerblurb {
    max-width: 42ch;
  }
}

@media (max-width: 760px) {
  .footer {
    padding: 40px 5vw 20px;
  }

  .footer .logo--footer {
    font-size: 27px;
    letter-spacing: -1.2px;
  }

  .footerblurb {
    font-size: 13px;
    max-width: 34ch;
  }

  .footercols {
    grid-template-columns: 1fr 1fr;
    gap: 26px 18px;
  }

  /* Phone: two shelves per row. An odd column count leaves one shelf alone on
     the last row, and a half-width shelf with a full-width gap beside it reads
     as a mistake, so that one stretches across. On a 3-column footer this is
     the "Fine print" row it has always been. */
  .footercol:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  .footer .footercol a {
    font-size: 12.5px;
    padding: 4px 0;
  }

  .footer .footercol h4 {
    margin-bottom: 8px;
  }

  .footerbottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    margin-top: 26px;
    padding-top: 16px;
    font-size: 10.5px;
  }
}

/* --- small screens: drop the deep end of the breadcrumb ------------------ */

@media (max-width: 560px) {
  /* "Home / Field notes / The cable on your desk is not in charge." wrapped,
     leaving a slash hanging at the end of the first line. Trim the deepest
     crumb, but only when the trail is long enough to wrap. */
  .pi-crumbs:has(> :nth-child(5)) > :nth-last-child(-n + 2) {
    display: none;
  }

  .pi-crumbs {
    margin-bottom: 2px;
  }

  /* An article's eyebrow already says "Field notes / Everyday · 1 min read";
     the crumb above it repeated the same words 26px higher. */
  .pi-article-page .pi-crumbs {
    display: none;
  }
}

@media (max-width: 480px) {
  .filter {
    padding: 9px 11px;
    font-size: 10.5px;
  }
}

/* --- search sheet -------------------------------------------------------- */

@media (max-width: 600px) {
  .pi-search-dialog {
    padding-top: 26px;
  }

  .pi-search-top h2 {
    font-size: 27px;
    line-height: 1.05;
  }

  /* The sample query is longer than the field; end it with an ellipsis rather
     than slicing a word in half against the Go button. */
  .pi-search-inputrow input {
    text-overflow: ellipsis;
  }

  .pi-search-label {
    margin-top: 18px;
  }
}

/* --- bag + checkout at one column --------------------------------------- */

@media (max-width: 900px) {
  .pi-cartpage,
  .pi-checkout {
    grid-template-columns: 1fr;
  }

  .pi-summary {
    position: static;
  }
}

/* ==========================================================================
   Nav levels, listing filters, the weekly board and the demo reel.

   Four across on desktop is the point of this block: three 390px squares in a
   1240px shell is a lookbook, not a shop. At four the tile lands near 250px,
   which is where a product photo is still legible next to its price while the
   eye can compare a row of them without scrolling.
   ========================================================================== */

.grid--products {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(16px, 1.7vw, 24px) clamp(10px, 1.1vw, 18px);
}

/* The grid holds four until it would squeeze a tile under ~210px, then three,
   then two — the count is driven by the space a card needs, not by the width
   of the window. */
@media (max-width: 1080px) {
  .grid--products {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .grid--products {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.grid--products .product h3 {
  font-size: 14.5px;
}

/* A 260px tile has no room for a title and a price on one line: the title
   wraps to three lines while the price sits in an 85px column, which is how
   "The Jar Opener" ends up stacked above its own subject line. Price goes
   under the title, which is also what every shop at this tile size does. */
.grid--products .product-info {
  display: block;
  padding: 11px 1px 0;
}

.grid--products .product-info .price {
  margin-top: 5px;
  font-size: 13px;
}

/* Two products fill a row; one gets a narrower card rather than a full-width
   hero tile that dwarfs everything above it. */
.grid--products[data-count="2"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid--products[data-count="1"] {
  grid-template-columns: minmax(0, 320px);
}

/* --- nav: text-only items ------------------------------------------------ */

/* An entry with no link is a label. It has to look like it belongs in the bar
   without inviting a click, so it keeps the type and loses the affordance. */
.navlinks__plain {
  color: var(--pi-muted);
  cursor: default;
  user-select: none;
}

.navdrop__toggle--btn {
  border: 0;
  background: transparent;
  padding: 0;
  min-height: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}

/* --- nav: the drawer's collapsible second level -------------------------- */

.mobile-nav__group {
  border-bottom: 1px solid var(--pi-line);
}

.mobile-nav__group > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 15px 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 21px;
  letter-spacing: -0.03em;
  list-style: none;
  cursor: pointer;
}

.mobile-nav__group > summary::-webkit-details-marker {
  display: none;
}

.mobile-nav__group > summary .pi-icon--chev {
  flex: none;
  transition: transform 0.18s ease;
}

.mobile-nav__group[open] > summary .pi-icon--chev {
  transform: rotate(180deg);
}

/* The sub-list is indented under a hairline, not given its own boxes: at
   drawer width, nested borders read as a second menu rather than as depth.
   It runs in two columns when the labels allow it. One column of ten entries
   is a scroll, not a menu: the reader loses the top of the section before
   reaching the bottom, and the groups below it are pushed off the screen.
   Column count is left to the labels (`auto-fit`), so a section of two short
   entries sits side by side and a long label takes the full width by itself. */
.mobile-nav__sub {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  column-gap: 16px;
  row-gap: 0;
  margin: 0 0 12px 2px;
  padding-left: 14px;
  border-left: 1px solid var(--pi-line);
}

.mobile-nav__sub a {
  padding: 9px 0;
  border-bottom: 0;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 13.5px;
  letter-spacing: 0;
  color: var(--pi-ink);
}

.mobile-nav__sub a:hover {
  color: var(--pi-orange);
}

/* Anything that is a caption rather than an entry spans the whole sub-list:
   a group heading over one column only would claim the links next to it. */
.mobile-nav__self,
.mobile-nav__subhead {
  grid-column: 1 / -1;
}

.mobile-nav__self {
  font-size: 10px !important;
  letter-spacing: 0.12em !important;
  text-transform: uppercase;
  color: var(--pi-muted) !important;
  padding: 4px 0 8px !important;
}

.mobile-nav__subhead {
  padding: 12px 0 4px;
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

/* The first heading sits directly under the section name (or under its "see
   everything" link), where an extra 12px of air turns it into a second title. */
.mobile-nav__subhead:first-child,
.mobile-nav__self + .mobile-nav__subhead {
  padding-top: 8px;
}

/* A text-only entry in the drawer: present, aligned with the links, clearly
   not one of them. */
.mobile-nav__text {
  display: block;
  padding: 15px 0;
  border-bottom: 1px solid var(--pi-line);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 21px;
  letter-spacing: -0.03em;
  color: var(--pi-muted);
}

/* --- listing: bar, sidebar, grid ---------------------------------------- */

/* Longhands only. `padding: 0 0 70px` would silently zero the left and right
   gutter that `.wrap` sets, and the grid would then run 144px wider than every
   other section on the page — a shorthand-vs-longhand collision that looks like
   a "the grid is broken" bug and is one line to avoid. */
.pi-listing {
  padding-bottom: 70px;
}

/* The bar is the shop's control panel: what you are looking at on the left,
   how many and in what order on the right. It is the first thing under the
   intro, so the count and the sort are read before any product is. */
.pi-listing__bar {
  display: flex;
  align-items: center;
  gap: 14px 18px;
  flex-wrap: wrap;
  margin: 26px 0 22px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--pi-line);
}

.pi-listing__bar .pi-resultcount {
  margin: 0;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pi-muted);
  font-variant-numeric: tabular-nums;
}

.pi-tools {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-left: auto;
  flex-wrap: wrap;
}

.pi-tool {
  display: flex;
  align-items: center;
  gap: 9px;
}

.pi-tool__label {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
  white-space: nowrap;
}

/* A native select, restyled rather than replaced.
   The browser's own popup is the only one that gets keyboard navigation,
   scroll-into-view and the phone's wheel picker right for free. The arrow is
   drawn with two borders so it matches the chevrons in the sidebar. */
.pi-select {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.pi-select select {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid var(--pi-line);
  background: var(--pi-white, #fffefa);
  color: var(--pi-ink);
  height: 38px;
  min-height: 38px;
  padding: 0 30px 0 10px;
  font-size: 12px;
  letter-spacing: -0.005em;
  border-radius: 0;
}

.pi-select::after {
  content: "";
  position: absolute;
  right: 11px;
  top: 50%;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid var(--pi-ink);
  border-bottom: 1.5px solid var(--pi-ink);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

.pi-select select:hover {
  border-color: var(--pi-ink);
}

.pi-select--num select {
  width: 68px;
  padding-right: 26px;
  font-variant-numeric: tabular-nums;
}

.pi-select--sort select {
  min-width: 196px;
}

/* --- listing: the two columns ------------------------------------------- */

.pi-listing__cols {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: clamp(26px, 3.2vw, 54px);
  align-items: start;
}

/* Three across, not four: the sidebar takes 232px plus its gutter, and four
   tiles in what is left lands under 200px, where a product photo stops being
   a photo. The [data-count] rules further up collapse a two-product grid into
   two huge tiles — correct on a four-column page, absurd beside a sidebar, so
   the count is ignored here and the column stays a column. */
.pi-listing .grid--products,
.pi-listing .grid--products[data-count="2"],
.pi-listing .grid--products[data-count="1"] {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.pi-facets {
  position: sticky;
  top: 96px;
  font-size: 12px;
}

.pi-facets__head {
  display: none;
}

/* --- listing: one facet group ------------------------------------------- */

.pi-facet {
  border-top: 1px solid var(--pi-line);
}

.pi-facet:last-of-type {
  border-bottom: 1px solid var(--pi-line);
}

/* A grid, not a flex row: the number, the name and the chevron then share one
   baseline even when a name wraps to two lines at 232px. */
.pi-facet__sum {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) 16px;
  align-items: center;
  gap: 4px;
  padding: 18px 0 16px;
  cursor: pointer;
  list-style: none;
}

.pi-facet__sum::-webkit-details-marker {
  display: none;
}

.pi-facet__no {
  font-size: 9px;
  letter-spacing: 0.06em;
  color: var(--pi-muted);
  font-variant-numeric: tabular-nums;
}

.pi-facet__name {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.pi-facet__chev {
  display: flex;
  justify-content: flex-end;
  color: var(--pi-ink);
}

.pi-facet__chev svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.2s ease;
}

/* Closed points right, open points down — the same triangle the phone uses
   for a menu, so it needs no legend. */
.pi-facet[open] .pi-facet__chev svg {
  transform: rotate(90deg);
}

.pi-facet__sum:hover .pi-facet__name {
  color: var(--pi-orange);
}

.pi-facet__body {
  display: grid;
  gap: 0;
  padding: 0 0 14px 22px;
}

.pi-facet__empty {
  margin: 0;
  padding: 0 8px 2px 0;
  font-size: 11px;
  line-height: 1.65;
  color: var(--pi-muted);
  max-width: 26ch;
}

.pi-facet__more {
  display: inline-block;
  justify-self: start;
  margin-top: 14px;
  padding-bottom: 3px;
  font-size: 9.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--pi-line);
}

.pi-facet__more:hover {
  border-color: var(--pi-ink);
}

/* The star rows with nothing behind them yet: same layout, no cursor, no
   counts — the shape of the filter the shop will have, not a promise it works
   today. */
.pi-facet__locked {
  display: grid;
}

.pi-fopt.is-off {
  cursor: default;
  opacity: 0.55;
}

.pi-fopt.is-off:hover {
  background: transparent;
}

.pi-fopt input:disabled + .pi-fopt__box {
  border-color: #dcdcd2;
  background: #f2f1ea;
}

.pi-facet__empty {
  margin-top: 8px;
}

/* --- listing: checkbox and radio rows ----------------------------------- */

/* The input is not `display: none`: it stays in the tab order and in the form's
   own data, it is just not the thing you look at. The visible box is a span
   drawn beside it, which is the only way to get a 15px square that is the same
   on Windows, macOS and iOS. */
.pi-fopt {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 0;
  cursor: pointer;
  font-size: 12.5px;
  line-height: 1.4;
}

.pi-fopt input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
  pointer-events: none;
}

.pi-fopt__box {
  flex: none;
  position: relative;
  width: 15px;
  height: 15px;
  border: 1px solid #b5b6ab;
  background: var(--pi-white, #fffefa);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pi-fopt__box--round {
  border-radius: 50%;
}

.pi-fopt input:checked + .pi-fopt__box {
  background: var(--pi-ink);
  border-color: var(--pi-ink);
}

/* A tick built from two borders rather than a glyph: at 15px every icon font
   and every emoji renders at a different weight, and this one is exact. */
.pi-fopt input:checked + .pi-fopt__box::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: 1.6px solid #fffdf8;
  border-top: 0;
  border-left: 0;
  transform: rotate(40deg);
}

.pi-fopt__text {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.pi-fopt__n {
  flex: none;
  font-size: 10px;
  color: var(--pi-muted);
  font-variant-numeric: tabular-nums;
}

/* Hover is a tint, not an underline: the row's text sits in a flex container,
   and `text-decoration` on a flex parent paints under the row rather than under
   the words — it would draw a line beneath the stars as well. */
.pi-fopt {
  margin: 0 -8px;
  padding: 6px 8px;
  transition: background-color 0.14s ease;
}

.pi-fopt:hover {
  background: rgba(228, 230, 217, 0.55);
}

.pi-fopt.is-on .pi-fopt__text {
  font-weight: 700;
}

.pi-fopt em {
  font-style: normal;
  font-weight: 400;
  font-size: 10.5px;
  color: var(--pi-muted);
}

.pi-fopt input:focus-visible + .pi-fopt__box {
  outline: 3px solid var(--pi-orange);
  outline-offset: 2px;
}

/* --- listing: the shelves under a department ---------------------------- */

/* Eleven shelf rows as flat siblings made the Type group read as eleven equal
   choices and pushed Price two screens down. Nested under a hairline, one size
   down and slightly muted, the departments stay the thing you scan and the
   shelves are the detail you drop into when a department is still too wide.
   The hairline starts at the parent's text column, so the eye reads "these
   belong to the row above" without an arrow or a second label. */
.pi-fopts--sub {
  /* Left edge lines up with the parent's words, not its checkbox. */
  margin: -3px 0 10px 24px;
  padding-left: 12px;
  border-left: 1px solid var(--pi-line);
}

.pi-fopts--sub .pi-fopt {
  margin: 0 -8px 0 -12px;
  padding: 5px 8px 5px 12px;
  font-size: 11.5px;
  color: var(--pi-muted);
}

.pi-fopts--sub .pi-fopt__box {
  width: 13px;
  height: 13px;
  border-color: #c3c4b9;
}

.pi-fopts--sub .pi-fopt input:checked + .pi-fopt__box::after {
  left: 3px;
  top: 1px;
  width: 4px;
  height: 7px;
  border-width: 1.4px;
}

.pi-fopts--sub .pi-fopt__n {
  font-size: 9.5px;
}

/* An unticked shelf is quieter than the department; ticking it, or hovering it,
   brings it back to ink so the active row never loses to its own parent. */
.pi-fopts--sub .pi-fopt.is-on,
.pi-fopts--sub .pi-fopt:hover {
  color: var(--pi-ink);
}

/* --- listing: the stars ------------------------------------------------- */

.pi-starrow {
  display: inline-flex;
  gap: 2px;
}

.pi-star {
  width: 12px;
  height: 12px;
  fill: #d3d4ca;
}

.pi-star.is-on {
  fill: var(--pi-orange);
}

/* --- listing: what is switched on --------------------------------------- */

/* A filter you cannot see is a filter you cannot trust. Each applied choice
   gets a chip with the one link that removes it, because "why is this grid
   showing four of six products" is otherwise a mystery on a page whose sidebar
   is scrolled off a phone screen. */
.pi-applied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0 0 18px;
}

.pi-applied__label {
  font-size: 9.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--pi-muted);
  margin-right: 2px;
}

.pi-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 9px;
  border: 1px solid var(--pi-line);
  background: var(--pi-white, #fffefa);
  font-size: 11px;
  line-height: 1;
}

.pi-chip span {
  color: var(--pi-muted);
  font-size: 13px;
  line-height: 1;
}

.pi-chip:hover {
  border-color: var(--pi-ink);
}

.pi-chip--clear {
  border-color: transparent;
  padding-left: 3px;
  color: var(--pi-orange);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- listing: nothing matched ------------------------------------------- */

.pi-empty {
  border: 1px solid var(--pi-line);
  padding: clamp(26px, 4vw, 44px);
  background: var(--pi-white, #fffefa);
}

.pi-empty__line {
  margin: 0 0 10px;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(21px, 2.4vw, 27px);
  line-height: 1.2;
  letter-spacing: -0.03em;
  max-width: 22ch;
}

.pi-empty__note {
  margin: 0 0 18px;
  max-width: 46ch;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--pi-muted);
}

.pi-empty__clear {
  display: inline-block;
  padding-bottom: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--pi-ink);
}

/* --- listing: the phone's filter button and drawer ---------------------- */

.pi-facets__open,
.pi-facets__close {
  display: none;
}

.pi-facets__scrim {
  display: none;
}

/* --- pagination ---------------------------------------------------------- */

/* Numbered pages, first/last always visible, a window around the current one,
   and an ellipsis for what is skipped. Centred and borderless above the rule,
   like the pager at the foot of every other shop — the old version put a
   "Page 3 / 12" label in the middle, which told you pages existed without
   giving you any way to reach page 7. */
.pi-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 34px;
  padding-top: 20px;
  border-top: 1px solid var(--pi-line);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.pi-pager__nums {
  display: flex;
  align-items: center;
  gap: 6px;
}

.pi-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--pi-line);
  padding: 10px 14px;
  line-height: 1;
  background: transparent;
}

.pi-page:hover {
  border-color: var(--pi-ink);
}

/* A number is a square target, not a pill: equal widths are what makes a row
   of them scan as "1, 2, 3" rather than as three unrelated buttons. */
.pi-page--num {
  min-width: 38px;
  padding: 11px 0;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
}

.pi-page--num.is-current {
  background: var(--pi-ink);
  border-color: var(--pi-ink);
  color: var(--pi-paper);
}

.pi-page.is-off {
  opacity: 0.35;
}

.pi-page__gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  color: var(--pi-muted);
  letter-spacing: 0;
}

/* Only on a phone, where the numbers give way to a plain count. */
.pi-pager__count {
  display: none;
  padding: 0 4px;
  color: var(--pi-muted);
  letter-spacing: 0.08em;
}

@media (max-width: 620px) {
  /* Seven 38px targets plus two arrows do not fit across 390px, and the
     version that does fit has targets too small to hit. The arrows stay:
     they are the two anyone actually uses at this width. */
  .pi-pager__nums {
    display: none;
  }

  .pi-pager__count {
    display: inline;
  }

  .pi-pager {
    gap: 6px;
    justify-content: space-between;
  }
}

/* --- the weekly trouble board ------------------------------------------- */

.pi-trouble-note {
  max-width: 32ch;
  margin: 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--pi-muted);
}

/* Seven cells on one rule: the week is a single object, not seven cards.
   Today opens the row, so the strip reads forward from now and the phone
   version starts on the day a visitor actually came for. */
.pi-week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--pi-line);
  border: 1px solid var(--pi-line);
}

.pi-day {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 170px;
  padding: 14px 13px 16px;
  background: var(--pi-paper);
  transition: background-color 0.18s ease;
}

/* A barely-warm lift on hover: enough to say the cell is a thing you can read
   across, not enough to compete with the inverted cell for today. */
.pi-day:hover {
  background: #fcfbf6;
}

/* Today is marked by its header alone: the bar carries the icon, the date and
   TODAY, and the body stays on paper. Filling the whole cell inverted it into a
   black block whose entries became the hardest text on the page to read — the
   marker should be loud, the content should not be dimmed to make it. */
.pi-day.is-today {
  background: #fdf8f1;
  color: var(--pi-ink);
}

.pi-day.is-today:hover {
  background: #fdf6ec;
}

.pi-day__head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding-bottom: 9px;
  border-bottom: 1px dotted var(--pi-line);
}

/* The filled part: the strip bleeds out to the cell edges and sits on the top
   corner like a tab, so today reads as "this one" from across the room while
   the seven columns keep running on the same 1px rule as before. */
.pi-day.is-today .pi-day__head {
  margin: -14px -13px 0;
  padding: 12px 13px;
  background: var(--pi-orange);
  color: var(--pi-ink);
  border-bottom: 0;
}

/* The weekday's own drawing, in a coin. Monoline icons, one stroke width, one
   currentColor — seven different pictures that still read as a set. */
.pi-day__chip {
  flex: 0 0 26px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--pi-line);
  border-radius: 50%;
  background: rgba(32, 33, 29, 0.035);
  color: #3d3f37;
  transition: color 0.18s ease, border-color 0.18s ease, transform 0.18s ease,
    background-color 0.18s ease;
}

.pi-day__chip svg {
  display: block;
  width: 15px;
  height: 15px;
}

.pi-day:hover .pi-day__chip {
  color: var(--pi-orange);
  border-color: rgba(232, 117, 63, 0.45);
  background: rgba(232, 117, 63, 0.07);
  transform: translateY(-1px);
}

/* On the orange bar the coin turns into a paper disc — the same orange icon on
   orange would vanish. */
.pi-day.is-today .pi-day__chip,
.pi-day.is-today:hover .pi-day__chip {
  color: var(--pi-ink);
  border-color: rgba(32, 33, 29, 0.4);
  background: rgba(255, 255, 255, 0.5);
  transform: none;
}

.pi-day__day {
  display: flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
}

.pi-day__name {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* The date number is what turns seven labels into a calendar. */
.pi-day__num {
  font-size: 10px;
  line-height: 1;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  opacity: 0.48;
}

.pi-day.is-today .pi-day__num {
  opacity: 0.72;
}

/* On the bar, orange-on-orange stops working: the label and its live dot go
   ink, which also keeps TODAY legible at 8.5px. */
.pi-day.is-today .pi-day__now {
  color: var(--pi-ink);
}

.pi-day.is-today .pi-day__now::before {
  background: currentColor;
  box-shadow: 0 0 0 3px rgba(32, 33, 29, 0.16);
}

.pi-day__now {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: auto;
  font-size: 8.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pi-orange);
  white-space: nowrap;
}

/* A live dot beside TODAY — the one moving thing in a static page. */
.pi-day__now::before {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 3px rgba(232, 117, 63, 0.18);
}

@media (prefers-reduced-motion: no-preference) {
  .pi-day__now::before {
    animation: pi-beat 2.6s ease-in-out infinite;
  }

  .pi-day.is-today .pi-day__now::before {
    animation-name: pi-beat-ink;
  }

  @keyframes pi-beat {
    0%,
    100% {
      box-shadow: 0 0 0 3px rgba(232, 117, 63, 0.18);
    }
    50% {
      box-shadow: 0 0 0 5px rgba(232, 117, 63, 0);
    }
  }

  @keyframes pi-beat-ink {
    0%,
    100% {
      box-shadow: 0 0 0 3px rgba(32, 33, 29, 0.16);
    }
    50% {
      box-shadow: 0 0 0 5px rgba(32, 33, 29, 0);
    }
  }
}

.pi-day__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}

.pi-day__list li {
  position: relative;
  padding-left: 10px;
  font-size: 12.5px;
  line-height: 1.4;
}

/* Tiny orange pip per entry: colour where the eye lands first, without a rule
   or a box that would fight the 1px grid. */
.pi-day__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.58em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--pi-orange);
  opacity: 0.55;
}

.pi-day.is-today .pi-day__list li::before {
  opacity: 0.78;
}

.pi-day__list a {
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}

.pi-day__list a:hover {
  color: var(--pi-orange);
}

.pi-day__list small {
  display: block;
  margin-top: 3px;
  font-size: 10.5px;
  line-height: 1.45;
  opacity: 0.62;
}

.pi-day__empty {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: 11px;
  opacity: 0.45;
}

.pi-day__empty svg {
  flex: 0 0 12px;
  width: 12px;
  height: 12px;
  color: var(--pi-orange);
  opacity: 0.8;
}

/* The clock the board runs on, said out loud. Sits under the strip, small. */
.pi-week__foot {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 11px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--pi-muted);
}

.pi-week__foot svg {
  flex: 0 0 13px;
  width: 13px;
  height: 13px;
  color: var(--pi-orange);
  opacity: 0.9;
}

.pi-week__foot b {
  font-weight: 500;
  color: var(--pi-ink);
}

/* Under ~1100px seven columns stop being readable, so the week becomes a
   swipeable strip rather than seven 90px slivers. Today is first, so the strip
   opens on the cell that matters instead of somewhere mid-week. */
@media (max-width: 1100px) {
  .pi-week {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }

  .pi-day {
    flex: 0 0 172px;
    scroll-snap-align: start;
  }
}

/* --- the demo reel ------------------------------------------------------ */

/* Longhands again, for the same reason as .pi-listing above. */
.pi-motion {
  padding-top: 8px;
  padding-bottom: 62px;
}

.pi-motion__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 26px;
  margin-bottom: 22px;
  padding-top: 26px;
  border-top: 1px solid var(--pi-line);
}

.pi-motion__head h2 {
  font-size: clamp(28px, 3.2vw, 44px);
  line-height: 1.05;
  margin: 8px 0 0;
}

.pi-motion__note {
  max-width: 32ch;
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-motion__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 20px);
}

.pi-motion__grid[data-count="1"] {
  grid-template-columns: minmax(0, 720px);
}

.pi-motion__grid[data-count="3"] {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* height:auto, no object-fit: an animation cropped to a square is a still. */
.pi-motion__frame {
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--pi-line);
  background: var(--pi-soft, #efefe7);
}

.pi-motion__frame img {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 760px) {
  .pi-motion__grid,
  .pi-motion__grid[data-count="3"] {
    grid-template-columns: 1fr;
  }

  .pi-motion__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .pi-motion__note {
    max-width: none;
  }

  .pi-motion {
    padding-bottom: 46px;
  }
}

/* --- home: the hero picture ----------------------------------------------
   Any picture, any shape. The frame IS the picture's ratio, handed over by the
   view for local files and by app.js for remote ones, so nothing is stretched
   and nothing is sliced. The old box was a fixed 440px tall with the picture
   bleeding out of it: a 3:1 banner kept its middle third, which on a score card
   meant losing the score. A very tall picture is handled by narrowing the frame
   instead of shortening it - the only way to keep the whole picture with no
   crop and no dead bands of background above and below it.
   ------------------------------------------------------------------------- */

.hero-art--photo {
  display: block;
  margin: 0;
  padding: 0;
  min-height: 0;
  aspect-ratio: auto;
  background: transparent;
  overflow: visible;
  /* Width first, height derived, and the caption follows the picture rather
     than the column: a very tall picture gets a narrower frame instead of a
     shorter one, which is the only way to keep it whole inside a hero without
     cropping it or leaving two dead bands of background above and below. */
  width: min(100%, calc(var(--pi-hero-cap, min(62vh, 620px)) * var(--pi-hero-ar, 1.5)));
  margin-inline: auto;
}

/* The photograph carries its own footer line, and the caption moved below the
   frame, so the old "SMALL FIXES. BETTER DAYS." stamp would print on top of it. */
.hero-art--photo::after {
  content: none;
}

.hero-art__frame {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: var(--pi-hero-ar, 1.5);
  background: #f6f1e4;
  border: 1px solid rgba(32, 33, 29, 0.14);
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 22px 50px -34px rgba(32, 33, 29, 0.55);
}

.hero-art__frame > img {
  display: block;
  width: 100%;
  height: 100%;
  /* The frame already has the picture's ratio, so this crops nothing. It is
     `cover` rather than `contain` only so a half-pixel rounding cannot leave a
     hairline of frame colour along one edge. */
  object-fit: cover;
  object-position: center;
}

/* Under the frame, not on it: text over a photograph is always a fight, and
   this text has nothing to do with the photograph. */
.hero-art__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 18px;
  margin: 12px 0 0;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.hero-art__meta .art-note,
.hero-art__meta .art-caption {
  position: static;
  color: inherit;
  text-shadow: none;
}

.hero-art__meta .art-caption {
  text-align: right;
  font-size: 11px;
  line-height: 1.45;
  letter-spacing: 0.06em;
  text-transform: none;
}

/* A wide picture belongs across the page, not in half of it. The copy moves up
   and splits into two short columns, so the banner still lands in the first
   screen instead of a scroll below it. */
.hero--banner {
  --pi-hero-cap: min(44vh, 440px);
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(24px, 3vw, 44px);
  padding-top: clamp(30px, 4vw, 54px);
  padding-bottom: clamp(28px, 3vw, 42px);
}

.hero--banner .hero__copy {
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
  gap: clamp(22px, 4vw, 64px);
  align-items: end;
}

.hero--banner h1 {
  font-size: clamp(2.6rem, 5vw, 4.6rem);
  max-width: 16ch;
  margin: 12px 0 0;
}

.hero--banner .hero__aside > p {
  max-width: 33rem;
  margin-bottom: 0;
}

.hero--banner .actions {
  margin-top: 20px;
}

@media (max-width: 760px) {
  .hero {
    --pi-hero-cap: min(58vh, 460px);
  }

  .hero--banner {
    gap: 20px;
  }

  .hero--banner .hero__copy {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }

  .hero--banner h1 {
    font-size: clamp(2rem, 9vw, 2.75rem);
    max-width: none;
    margin-bottom: 0;
  }

  .hero--banner .actions {
    margin-top: 20px;
  }

  .hero--banner .hero-art__frame {
    max-height: none;
  }

  .hero-art__meta {
    flex-direction: column;
    gap: 2px;
    margin-top: 9px;
  }

  .hero-art__meta .art-caption {
    text-align: left;
  }
}

/* --- home: the manifesto plate -------------------------------------------
   Same rule as the hero, opposite answer. The hero picture goes across the
   whole page; this one stays in its own column and grows to fill it, so the
   band reads as two halves - picture and argument - instead of a second
   banner. The frame takes the picture's ratio too, so an unusual shape makes
   the plate narrower rather than lopping a piece off it.
   ------------------------------------------------------------------------ */

.manifesto {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(30px, 4.6vw, 72px);
  align-items: center;
  padding: clamp(46px, 5.2vw, 76px) 8vw;
}

.manifesto__figure {
  margin: 0;
  min-width: 0;
}

.manifesto__figure .eyebrow {
  margin-bottom: 12px;
}

.manifesto__frame {
  display: block;
  width: min(100%, calc(var(--pi-manifesto-cap, min(54vh, 520px)) * var(--pi-manifesto-ar, 1)));
  aspect-ratio: var(--pi-manifesto-ar, 1);
  overflow: hidden;
  border-radius: 2px;
  background: #f7f6f1;
  box-shadow: 0 26px 46px -34px rgba(24, 25, 20, 0.45);
}

.manifesto__frame > img {
  display: block;
  width: 100%;
  height: 100%;
  /* The frame already has the picture's ratio, so nothing is cropped. */
  object-fit: cover;
  object-position: center;
}

.manifesto .svg-editorial {
  margin-top: 0;
}

@media (max-width: 900px) {
  .manifesto {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
    align-items: start;
  }
  /* Stacked, the plate goes edge to edge like every other picture on a phone.
     The height cap in the base rule still narrows it on short screens. */
}

/* --- small screens ------------------------------------------------------ */

/* Under 1140px the sidebar is a drawer.
   232px of sidebar plus a 46px gutter leaves a three-column grid at 209px a
   tile — narrow enough that a product photo stops being a product photo. The
   breakpoint is where the column would squeeze the grid, not where the window
   "looks like a tablet". It slides in from the right, which is the edge the
   "Filters" button sits on. */
@media (max-width: 1140px) {
  .pi-listing__cols {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }

  .pi-facets {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(360px, 88vw);
    z-index: 9001;
    background: var(--pi-paper);
    padding: 0 20px 48px;
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(102%);
    visibility: hidden;
    transition: transform 0.26s cubic-bezier(0.3, 0.7, 0.2, 1), visibility 0s linear 0.26s;
    box-shadow: -24px 0 60px rgba(20, 21, 18, 0.2);
  }

  .pi-facets.is-open {
    transform: none;
    visibility: visible;
    transition: transform 0.26s cubic-bezier(0.3, 0.7, 0.2, 1), visibility 0s;
  }

  .pi-facets__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 -20px;
    padding: 16px 20px 14px;
    background: var(--pi-paper);
    border-bottom: 1px solid var(--pi-line);
  }

  .pi-facets__title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .pi-facets__title b {
    font-weight: 700;
    color: var(--pi-orange);
  }

  .pi-facets__close {
    display: block;
    width: 38px;
    height: 38px;
    margin-right: -6px;
    border: 0;
    background: transparent;
    font-size: 26px;
    line-height: 1;
    color: var(--pi-ink);
  }

  .pi-facets__open {
    display: inline-flex;
    margin-left: auto;
    align-items: center;
    gap: 7px;
    padding: 9px 12px;
    border: 1px solid var(--pi-ink);
    background: var(--pi-white, #fffefa);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }

  .pi-facets__open span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    background: var(--pi-orange);
    color: #fff;
    font-size: 10px;
    letter-spacing: 0;
  }

  /* The scrim is a real element, not a pseudo-element: it has to be clickable
     to close the drawer. */
  .pi-facets__scrim:not([hidden]) {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 9000;
    background: rgba(22, 23, 19, 0.46);
    border: 0;
    padding: 0;
    min-height: 0;
  }

  body.pi-facets-open {
    overflow: hidden;
  }

  .pi-listing__bar {
    margin-top: 18px;
  }

  /* The count and the Filters button share a line; the two selects get the
     next one to themselves, because "Show per page 24" plus "Sort by …" does
     not fit beside a button at 390px. */
  .pi-tools {
    width: 100%;
    margin-left: 0;
    gap: 12px;
    justify-content: space-between;
  }
}

@media (max-width: 760px) {
  .pi-listing .grid--products,
  .pi-listing .grid--products[data-count="2"],
  .pi-listing .grid--products[data-count="1"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pi-page--step {
    padding: 10px 12px;
  }

  /* Two cards and a peek of the third: enough to read the day you are on and
     see that there is more week to the right. */
  .pi-day {
    flex-basis: 46vw;
    min-height: 132px;
    padding: 13px 12px 15px;
  }

  .pi-select--sort select {
    min-width: 0;
    width: 100%;
  }

  .pi-tool {
    flex: 1;
    min-width: 0;
  }

  .pi-tool--sort {
    flex: 1.4;
  }
}

@media (max-width: 460px) {
  .pi-tool {
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
  }

  /* Stacked labels above their selects read as two fields, not one ragged
     row: both selects then take the full half-width column. */
  .pi-select,
  .pi-select select,
  .pi-select--num select {
    width: 100%;
  }

  .pi-tool__label {
    font-size: 9px;
  }

  .pi-select--sort select {
    min-width: 0;
  }

  .pi-facets {
    width: min(330px, 92vw);
    padding: 0 16px 44px;
  }

  .pi-facets__head {
    margin: 0 -16px;
    padding: 14px 16px 12px;
  }
}

/* Print: an order confirmation should print cleanly. */
@media print {
  .nav,
  .announcement,
  .footer,
  .pi-search-backdrop,
  .pi-added-backdrop,
  .pi-bag-backdrop,
  .mobile-nav,
  .pi-facets,
  .pi-listing__bar,
  .pi-applied,
  .pi-pager,
  .btn,
  .textlink {
    display: none !important;
  }
}

/* ==========================================================================
   Journal covers

   The card used to be a numbered ✳ block. It is now the article's own photo:
   the 封面图 field, or the first image in the body. Same 3:2 box either way,
   so a missing cover still lines up with the ones that have a photo.
   ========================================================================== */

.blogvisual--photo {
  display: block;
  padding: 0;
  overflow: hidden;
  background: #e1e0d6;
}

.blogvisual--photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform 0.5s ease;
}

.blogcard:hover .blogvisual--photo img {
  transform: scale(1.025);
}

@media (prefers-reduced-motion: reduce) {
  .blogcard:hover .blogvisual--photo img {
    transform: none;
  }
}

/* ==========================================================================
   Product case-file accordion

   The rows are ✳ / title + sub-line / +, separated by hairlines. The markup
   carries the three spans; this block only handles the details/summary bits
   the theme left to the browser (marker, cursor, tap target).
   ========================================================================== */

.product-accordions .accord summary {
  cursor: pointer;
  outline-offset: 2px;
}

.product-accordions .accord summary:focus-visible {
  outline: 2px solid var(--orange);
}

.product-accordions .accord summary::-webkit-details-marker,
.product-accordions .accord summary::marker {
  display: none;
  content: '';
}

.accord-copy strong {
  text-transform: uppercase;
  font-weight: 800;
}

.accord-plus {
  line-height: 1;
}

.product-accordions .accord[open] .accord-plus {
  color: var(--orange);
}

/* The body hangs off the summary's icon column: 4px padding + 42px mark +
   18px gap. The theme's 60px left the copy 4px to the left of the title. */
.product-accordions .accord p {
  margin-left: 64px;
}

@media (max-width: 760px) {
  .product-accordions .accord p {
    margin-left: 44px;
    margin-right: 8px;
    font-size: 14px;
    line-height: 1.65;
  }
}

/* ==========================================================================
   Trouble level assessment

   A case file that grades the visitor. The shape is deliberately a form, not a
   card grid: banner, case strip, then either the questions or the verdict. One
   thing at a time is what makes three questions feel like thirty seconds and
   not like a survey.

   The accent per grade lives on `[data-level]` on the outer .pi-case, so the
   verdict, the rubber stamp and the certificate all change colour from one
   attribute the script sets.
   ========================================================================== */

.pi-quizsection .section-head {
  align-items: end;
}

.pi-quiz__note {
  max-width: 34ch;
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-case {
  --lv: #3f443a;
  --lv-soft: #eef0e7;
  background: #fffefa;
  border: 1px solid var(--pi-line);
  border-radius: 3px;
  padding: clamp(20px, 2.6vw, 38px);
}

.pi-case[data-level='0'] {
  --lv: #557f4f;
  --lv-soft: #e9efe1;
}

.pi-case[data-level='1'] {
  --lv: #b4761c;
  --lv-soft: #f8eed9;
}

.pi-case[data-level='2'] {
  --lv: #bc4233;
  --lv-soft: #f7e3de;
}

/* --- banner ------------------------------------------------------------- */

.pi-case__top {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(14px, 2.4vw, 30px);
  align-items: center;
}

.pi-case__beacon {
  position: relative;
  display: grid;
  place-items: center;
  width: 68px;
  height: 68px;
  flex: none;
}

.pi-case__beacon svg {
  position: relative;
  width: 44px;
  height: 44px;
  display: block;
}

.pi-beacon__glow {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, rgba(217, 70, 58, 0.16), rgba(217, 70, 58, 0) 70%);
  animation: pi-beacon 2.6s ease-in-out infinite;
}

@keyframes pi-beacon {
  0%,
  100% {
    opacity: 0.55;
    transform: scale(0.9);
  }
  50% {
    opacity: 1;
    transform: scale(1.06);
  }
}

.pi-case__titles {
  min-width: 0;
}

.pi-case__kick {
  display: inline-block;
  background: #f2c84b;
  color: #20211d;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 4px 10px 3px;
  transform: rotate(-1.4deg);
}

.pi-case__word {
  font-size: clamp(30px, 4.4vw, 54px);
  line-height: 0.98;
  font-weight: 900;
  letter-spacing: -0.05em;
  text-transform: uppercase;
  margin: 12px 0 0;
}

.pi-case__verdict {
  display: inline-block;
  margin: 12px 0 0;
  padding-bottom: 3px;
  border-bottom: 2px solid currentColor;
  color: var(--lv);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  line-height: 1.4;
}

.pi-case__checklist {
  display: grid;
  gap: 9px;
  padding: 14px 16px;
  background: var(--pi-soft);
  border: 1px solid var(--pi-line);
  transform: rotate(1.2deg);
}

.pi-check {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 11.5px;
  line-height: 1.3;
  color: #8d8f83;
}

.pi-check::before {
  content: '';
  flex: none;
  width: 12px;
  height: 12px;
  margin-top: 1px;
  border: 1.5px solid #b9b5a6;
  background: #fffefa;
}

.pi-check.is-on {
  color: var(--pi-ink);
  font-weight: 700;
}

.pi-check.is-on::before {
  border-color: var(--pi-ink);
  background: var(--pi-ink)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.4 6.1l2.4 2.5 4.8-5.3' fill='none' stroke='%23fffefa' stroke-width='1.9'/%3E%3C/svg%3E")
    center / 10px no-repeat;
}

/* --- case strip --------------------------------------------------------- */

.pi-case__strip {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: clamp(14px, 2vw, 26px);
  align-items: center;
  margin: clamp(18px, 2.4vw, 26px) calc(-1 * clamp(20px, 2.6vw, 38px)) clamp(18px, 2.4vw, 26px);
  padding: 14px clamp(16px, 2.4vw, 26px);
  background: var(--lv-soft);
  border-top: 1px solid rgba(32, 33, 29, 0.07);
  border-bottom: 1px solid rgba(32, 33, 29, 0.07);
}

.pi-strip__case {
  padding-right: clamp(14px, 2vw, 26px);
  border-right: 1px solid rgba(32, 33, 29, 0.16);
}

.pi-strip__case strong {
  display: block;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.11em;
  white-space: nowrap;
}

.pi-strip__case small {
  display: block;
  margin-top: 3px;
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #5d6057;
}

.pi-strip__quote {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: #4b4e46;
}

.pi-seal {
  display: grid;
  place-items: center;
  min-width: 96px;
  padding: 13px 17px;
  border: 2px solid currentColor;
  border-radius: 50%;
  color: var(--lv);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.25;
  transform: rotate(-7deg);
  box-shadow: inset 0 0 0 2px #fffefa, inset 0 0 0 3px currentColor;
}

.pi-seal[hidden] {
  display: none;
}

/* --- questions ---------------------------------------------------------- */

.pi-quiz {
  padding-top: 4px;
}

.pi-quiz__meta {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--pi-muted);
  font-variant-numeric: tabular-nums;
}

.pi-quiz__bar {
  flex: 1;
  height: 2px;
  background: var(--pi-line);
  overflow: hidden;
}

.pi-quiz__bar i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--pi-ink);
  transition: width 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.pi-quiz__prompt {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(21px, 2.3vw, 28px);
  line-height: 1.24;
  letter-spacing: -0.035em;
  margin: 16px 0 20px;
  max-width: 30ch;
}

.pi-quiz__options {
  display: grid;
  gap: 8px;
}

.pi-opt {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  width: 100%;
  min-height: 56px;
  padding: 13px 16px;
  text-align: left;
  background: #fffefa;
  border: 1px solid var(--pi-line);
  font-size: 13.5px;
  line-height: 1.45;
  transition: border-color 0.16s ease, background 0.16s ease, color 0.16s ease;
}

.pi-opt:hover,
.pi-opt:focus-visible {
  border-color: var(--pi-ink);
  background: var(--pi-soft);
}

.pi-opt.is-picked {
  border-color: var(--pi-ink);
  background: var(--pi-ink);
  color: var(--pi-paper);
}

.pi-opt__key {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--pi-line);
  font-size: 10.5px;
  font-weight: 700;
  color: var(--pi-muted);
}

.pi-opt.is-picked .pi-opt__key {
  border-color: rgba(247, 246, 241, 0.5);
  color: var(--pi-paper);
}

.pi-opt__arrow {
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 0.16s ease, transform 0.16s ease;
}

.pi-opt:hover .pi-opt__arrow,
.pi-opt.is-picked .pi-opt__arrow {
  opacity: 1;
  transform: translateX(0);
}

.pi-quiz__none {
  font-size: 13px;
  color: var(--pi-muted);
}

/* --- result ------------------------------------------------------------- */

.pi-result {
  animation: pi-rise 0.4s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.pi-result[hidden] {
  display: none;
}

@keyframes pi-rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.pi-result__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  gap: clamp(20px, 4vw, 46px);
  align-items: center;
  padding-top: 6px;
}

.pi-result__tag {
  display: inline-block;
  background: var(--pi-ink);
  color: var(--pi-paper);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  padding: 5px 9px 4px;
}

.pi-result h3 {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(26px, 3vw, 38px);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.045em;
  margin: 16px 0 14px;
  max-width: 18ch;
}

.pi-result__copy p {
  margin: 0;
  max-width: 46ch;
  font-size: 14px;
  line-height: 1.72;
  color: #55584f;
}

.pi-art {
  display: block;
  width: 100%;
  height: auto;
  background: #f6f2e7;
  border-radius: 3px;
}

/* --- certificate -------------------------------------------------------- */

.pi-cert {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  margin-top: clamp(20px, 3vw, 30px);
  padding: 17px 20px;
  background: var(--pi-soft);
  border-left: 3px solid var(--lv);
}

.pi-cert small {
  display: block;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #6f7268;
}

.pi-cert strong {
  display: block;
  margin: 6px 0;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(17px, 1.9vw, 22px);
  font-weight: 400;
  letter-spacing: -0.025em;
  line-height: 1.25;
}

.pi-cert__star {
  font-size: 26px;
  line-height: 1;
  color: var(--pi-orange);
  flex: none;
}

/* --- the shop part ------------------------------------------------------ */

.pi-result__shop {
  margin-top: clamp(22px, 3vw, 32px);
}

.pi-result__shophead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  border-top: 1px solid var(--pi-line);
  padding-top: 15px;
  margin-bottom: 18px;
}

.pi-result__shophead h4 {
  margin: 0;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.pi-again {
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--pi-muted);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.pi-again:hover {
  color: var(--pi-ink);
}

.pi-quiz__set[hidden] {
  display: none;
}

.pi-result__actions {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 22px;
}

/* --- narrow ------------------------------------------------------------- */

@media (max-width: 900px) {
  .pi-case__checklist {
    display: none;
  }

  .pi-case__top {
    grid-template-columns: auto minmax(0, 1fr);
  }
}

@media (max-width: 860px) {
  .pi-result__grid {
    grid-template-columns: 1fr;
  }

  .pi-art {
    order: -1;
    max-width: 420px;
  }
}

@media (max-width: 760px) {
  .pi-quizsection .section-head {
    align-items: flex-start;
  }

  .pi-case__beacon {
    width: 46px;
    height: 46px;
  }

  .pi-case__beacon svg {
    width: 34px;
    height: 34px;
  }

  .pi-case__word {
    font-size: clamp(27px, 8.6vw, 40px);
  }

  .pi-case__strip {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 10px;
  }

  .pi-strip__case {
    border-right: 0;
    padding-right: 0;
  }

  .pi-strip__quote {
    grid-column: 1 / -1;
    font-size: 12.5px;
  }

  .pi-seal {
    min-width: 82px;
    padding: 10px 13px;
    font-size: 9px;
  }

  .pi-opt {
    grid-template-columns: auto minmax(0, 1fr);
    font-size: 13px;
    padding: 13px 14px;
  }

  .pi-opt__arrow {
    display: none;
  }

  .pi-result h3 {
    font-size: clamp(25px, 7.6vw, 32px);
  }

  .pi-cert {
    padding: 15px 16px;
  }

  .pi-cert__star {
    font-size: 20px;
  }

  .pi-result__shophead {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
}

/* ==========================================================================
   The trouble check page

   The assessment used to sit in the middle of the home page and was too big
   for that job: three questions, a verdict, a certificate and three product
   grids is a page. It now owns /trouble-check/ and gets the layout a page can
   afford — a two-column hero with a physical intake form on the right, a
   running strip of findings, the assessment itself, the case archive, and a
   closing band that points at the shop.

   Everything below is scaffolding for that one URL. The assessment card keeps
   its own `.pi-case*` block further up this file, unchanged, so the same markup
   could still be dropped anywhere if the owner ever wants it back.
   ========================================================================== */

.pi-trouble__top {
  padding-top: 32px;
}

.pi-trouble__hero {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(26px, 5vw, 76px);
  align-items: center;
  padding: clamp(22px, 3vw, 40px) 0 clamp(34px, 5vw, 62px);
}

.pi-trouble__intro h1 {
  font-size: clamp(2.9rem, 6.4vw, 6rem);
  line-height: 0.9;
  letter-spacing: -0.07em;
  margin: 14px 0 0;
  max-width: 15ch;
}

.pi-trouble__intro h1 em {
  font-style: italic;
  color: var(--pi-orange);
}

.pi-trouble__lede {
  margin: 20px 0 0;
  max-width: 44ch;
  font-size: 15.5px;
  line-height: 1.72;
  color: #55584f;
}

.pi-trouble__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-trouble__meta li {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 0 14px;
  border-left: 1px solid var(--pi-line);
}

.pi-trouble__meta li:first-child {
  padding-left: 0;
  border-left: 0;
}

.pi-trouble__meta b {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 17px;
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--pi-ink);
  font-variant-numeric: tabular-nums;
}

.pi-trouble__note {
  margin: 18px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--pi-muted);
  max-width: 40ch;
}

/* --- the intake form ----------------------------------------------------- */

.pi-form {
  position: relative;
  padding: clamp(18px, 2.2vw, 28px);
  background: #fffefa;
  border: 1px solid var(--pi-line);
  transform: rotate(-1.5deg);
  box-shadow: 12px 14px 0 rgba(32, 33, 29, 0.04);
}

.pi-form__tape {
  position: absolute;
  top: -11px;
  width: 84px;
  height: 21px;
  background: rgba(228, 222, 202, 0.86);
  border-left: 1px solid rgba(32, 33, 29, 0.05);
  border-right: 1px solid rgba(32, 33, 29, 0.05);
}

.pi-form__tape--l {
  left: 22px;
  transform: rotate(-5deg);
}

.pi-form__tape--r {
  right: 22px;
  transform: rotate(4deg);
}

.pi-form__head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 9px;
  border-bottom: 1.5px solid var(--pi-ink);
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.pi-form__rows {
  margin: 6px 0 0;
  padding: 0;
}

.pi-form__rows > div {
  display: grid;
  grid-template-columns: 82px minmax(0, 1fr);
  gap: 12px;
  align-items: baseline;
  padding: 11px 0 9px;
  border-bottom: 1px dashed var(--pi-line);
}

.pi-form__rows dt {
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8b8e83;
}

.pi-form__rows dd {
  margin: 0;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 15px;
  line-height: 1.35;
  letter-spacing: -0.02em;
}

.pi-form__pending {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12.5px;
  letter-spacing: 0;
  color: var(--pi-ink);
  background: linear-gradient(transparent 58%, #f2c84b 58%);
  padding: 0 2px;
}

.pi-form__stamp {
  position: absolute;
  right: clamp(16px, 2.4vw, 26px);
  bottom: clamp(30px, 4vw, 44px);
  padding: 5px 11px 3px;
  border: 2.5px solid #bd4132;
  border-radius: 3px;
  color: #bd4132;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.82;
  transform: rotate(-11deg);
  pointer-events: none;
}

.pi-form__foot {
  margin: 16px 0 0;
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #9b9d92;
}

/* --- the findings strip -------------------------------------------------- */

.pi-ticker {
  overflow: hidden;
  background: var(--pi-ink);
  color: #eceae0;
}

.pi-ticker__track {
  display: flex;
  width: max-content;
  animation: pi-marquee 52s linear infinite;
}

.pi-ticker:hover .pi-ticker__track {
  animation-play-state: paused;
}

.pi-ticker__item {
  display: inline-flex;
  align-items: center;
  gap: 20px;
  padding: 13px 20px;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.pi-ticker__item i {
  font-style: normal;
  color: var(--pi-orange);
}

@keyframes pi-marquee {
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .pi-ticker {
    overflow-x: auto;
  }

  .pi-ticker__track {
    animation: none;
  }
}

/* --- the assessment ------------------------------------------------------ */

.pi-trouble__body {
  padding-top: clamp(38px, 5vw, 66px);
}

#assessment {
  scroll-margin-top: 24px;
}

.pi-quiz__rail {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 16px;
}

.pi-quiz__dots {
  display: flex;
  gap: 5px;
}

.pi-quiz__dots i {
  width: 26px;
  height: 3px;
  background: var(--pi-line);
  transition: background 0.2s ease;
}

.pi-quiz__dots i.is-done {
  background: var(--pi-ink);
}

.pi-quiz__dots i.is-now {
  background: var(--pi-orange);
}

.pi-quiz__step {
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #9b9d92;
  font-variant-numeric: tabular-nums;
}

.pi-quiz__step b {
  font-weight: 700;
  color: var(--pi-ink);
}

.pi-quiz__after {
  min-height: 48px;
  padding-top: 14px;
}

.pi-quiz__reaction {
  margin: 0;
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--pi-ink);
  animation: pi-rise 0.3s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.pi-quiz__reaction::before {
  content: 'Inspector —';
  margin-right: 9px;
  font-family: Arial, Helvetica, sans-serif;
  font-style: normal;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--pi-orange);
  vertical-align: 1px;
}

.pi-quiz__hint {
  margin: 0;
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #9b9d92;
}

.pi-quiz__hint kbd {
  display: inline-grid;
  place-items: center;
  min-width: 17px;
  height: 17px;
  margin: 0 2px;
  padding: 0 3px;
  border: 1px solid var(--pi-line);
  background: #fffefa;
  font-family: inherit;
  font-size: 9px;
  color: var(--pi-ink);
  vertical-align: 1px;
}

.pi-case.is-reacting .pi-opt:not(.is-picked) {
  opacity: 0.4;
}

.pi-case.is-reacting .pi-quiz__hint {
  visibility: hidden;
}

/* --- the meter ----------------------------------------------------------- */

.pi-meter {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--pi-line);
}

.pi-meter__bar {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 28px;
}

.pi-meter__zones {
  position: absolute;
  left: 0;
  right: 0;
  top: 13px;
  height: 5px;
  display: flex;
  background: var(--pi-line);
}

.pi-meter__zone[data-zone='0'] {
  background: #8fa47c;
}

.pi-meter__zone[data-zone='1'] {
  background: #cda548;
}

.pi-meter__zone[data-zone='2'] {
  background: #c35a44;
}

.pi-meter__ticks i {
  position: absolute;
  top: 20px;
  width: 1px;
  height: 5px;
  background: rgba(32, 33, 29, 0.22);
}

.pi-meter__needle {
  position: absolute;
  top: 2px;
  width: 2px;
  height: 18px;
  background: var(--pi-ink);
  transition: left 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.pi-meter__needle i {
  position: absolute;
  top: -5px;
  left: 50%;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  border-radius: 50%;
  background: var(--pi-ink);
}

.pi-meter__read {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: none;
  text-align: right;
  white-space: nowrap;
}

.pi-meter__read span {
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8b8e83;
}

.pi-meter__read b {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 17px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

/* --- case archive -------------------------------------------------------- */

.pi-archive__note {
  max-width: 36ch;
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-archive__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
}

.pi-folder-card {
  position: relative;
  padding-top: 27px;
  --lv: #557f4f;
}

.pi-folder-card[data-zone='1'] {
  --lv: #b4761c;
}

.pi-folder-card[data-zone='2'] {
  --lv: #bc4233;
}

.pi-folder-card__tab {
  position: absolute;
  top: 0;
  left: 0;
  padding: 6px 14px 7px;
  border: 1px solid var(--pi-line);
  border-bottom: 0;
  background: #e8e4d7;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #4b4e46;
}

.pi-folder-card__body {
  height: 100%;
  padding: clamp(18px, 2vw, 25px);
  background: #fffefa;
  border: 1px solid var(--pi-line);
}

.pi-folder-card__seal {
  display: inline-block;
  padding: 4px 9px 3px;
  border: 1.5px solid currentColor;
  color: var(--lv);
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  transform: rotate(-2.5deg);
}

.pi-folder-card h3 {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(23px, 2.3vw, 29px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.045em;
  margin: 15px 0 9px;
}

.pi-folder-card__verdict {
  margin: 0 0 12px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.11em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--lv);
}

.pi-folder-card__line {
  margin: 0 0 16px;
  font-size: 13.5px;
  line-height: 1.62;
  color: #55584f;
}

.pi-folder-card__picks {
  display: grid;
  gap: 7px;
  padding-top: 13px;
  border-top: 1px solid var(--pi-line);
}

.pi-folder-card__picks a {
  font-size: 12px;
  letter-spacing: 0.01em;
  color: #3c3f37;
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  width: fit-content;
}

.pi-folder-card__picks a:hover {
  border-bottom-color: var(--pi-ink);
}

/* --- closing band -------------------------------------------------------- */

.pi-closing {
  margin-top: clamp(48px, 6vw, 84px);
  padding: clamp(44px, 6vw, 76px) 0;
  background: var(--pi-ink);
  color: var(--pi-paper);
}

.pi-closing__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) auto;
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
}

.pi-closing .eyebrow {
  color: #a2a599 !important;
}

.pi-closing h2 {
  margin: 10px 0 0;
  font-size: clamp(29px, 4.2vw, 52px);
  line-height: 1;
  color: var(--pi-paper);
  max-width: 18ch;
}

.pi-closing p {
  margin: 16px 0 0;
  max-width: 48ch;
  font-size: 14px;
  line-height: 1.72;
  color: #c4c5bb;
}

.pi-closing__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.pi-closing .btn {
  background: var(--pi-paper);
  border-color: var(--pi-paper);
  color: var(--pi-ink);
}

.pi-closing .btn.light {
  background: transparent;
  border-color: #5c5f55;
  color: var(--pi-paper);
}

/* --- narrow ------------------------------------------------------------- */

@media (max-width: 980px) {
  .pi-trouble__hero {
    grid-template-columns: 1fr;
    align-items: start;
  }

  .pi-trouble__intro h1 {
    max-width: 18ch;
  }

  .pi-trouble__cover {
    max-width: 460px;
  }

  .pi-archive__grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }

  .pi-closing__inner {
    grid-template-columns: 1fr;
    align-items: start;
  }
}

@media (max-width: 760px) {
  .pi-trouble__top {
    padding-top: 18px;
  }

  .pi-trouble__intro h1 {
    font-size: clamp(2.35rem, 11vw, 3.6rem);
    max-width: 20ch;
  }

  .pi-trouble__lede {
    font-size: 14.5px;
  }

  .pi-trouble__meta {
    font-size: 10px;
    row-gap: 8px;
  }

  .pi-trouble__meta li {
    padding: 0 12px 0 0;
    border-left: 0;
  }

  .pi-trouble__meta b {
    font-size: 15px;
  }

  .pi-form {
    transform: none;
    box-shadow: 7px 8px 0 rgba(32, 33, 29, 0.04);
  }

  .pi-form__rows > div {
    grid-template-columns: 68px minmax(0, 1fr);
    gap: 10px;
  }

  .pi-form__stamp {
    font-size: 10px;
    padding: 4px 9px 2px;
  }

  .pi-form__foot {
    padding-right: 72px;
  }

  .pi-ticker__item {
    padding: 11px 14px;
    font-size: 9.5px;
    gap: 14px;
  }

  .pi-meter {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }

  /* `flex: 1` means "grow along the main axis", and the main axis just became
     vertical — the bar would collapse to zero height. Pin it instead. */
  .pi-meter__bar {
    flex: none;
    width: 100%;
    height: 28px;
  }

  .pi-meter__read {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    text-align: left;
  }

  .pi-quiz__reaction {
    font-size: 14.5px;
  }

  .pi-quiz__hint {
    display: none;
  }

  .pi-archive__grid {
    gap: 12px;
  }

  .pi-closing__actions .btn {
    flex: 1;
  }
}

/* ==========================================================================
   Subscription: the band's confirmation state, and the entry popup.

   The popup is a <dialog>, which means the backdrop, Esc and focus trapping
   are the browser's job, not a div with a z-index and a scroll lock that
   forgets to unlock. Only the paper is ours to draw.
   ========================================================================== */

.newsletter__form {
  width: 100%;
  max-width: 440px;
}

.newsletter__done,
.pi-popup__done {
  margin: 0;
  padding: 11px 14px;
  background: #eeeadd;
  border-left: 2px solid var(--pi-orange);
  font-size: 13px;
  line-height: 1.5;
  color: #3c3f36;
}

/* `[hidden]` loses to any rule that sets display, and both the band form and
   the popup form are flex containers. Say it once, loudly. */
.newsletter [hidden],
.pi-popup [hidden] {
  display: none !important;
}

.pi-popup {
  width: min(520px, calc(100vw - 32px));
  max-height: min(88vh, 760px);
  padding: 0;
  /* One orange rule along the top edge instead of a decorative shape: the
     same accent the ticker uses, at 3px, reads as a printed tab. */
  border: 1px solid rgba(32, 33, 29, 0.18);
  border-top: 3px solid var(--pi-orange);
  background: #f8f5ea;
  color: var(--pi-ink);
  overflow: hidden;
  box-shadow: 0 40px 90px -40px rgba(20, 21, 17, 0.65);
}

.pi-popup:not([open]) {
  display: none;
}

.pi-popup::backdrop {
  background: rgba(22, 23, 19, 0.56);
}

.pi-popup[open] {
  animation: pi-pop-in 0.32s cubic-bezier(0.2, 0.7, 0.3, 1);
}

@keyframes pi-pop-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pi-popup[open] {
    animation: none;
  }
}

.pi-popup__card {
  position: relative;
  padding: 32px 34px 26px;
  overflow-y: auto;
  max-height: inherit;
}

.pi-popup__figure {
  margin: -32px -34px 22px;
}

.pi-popup__figure img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.pi-popup__x {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 34px;
  height: 34px;
  border: 0;
  background: transparent;
  color: #8b8d82;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.pi-popup__x:hover,
.pi-popup__x:focus-visible {
  color: var(--pi-ink);
}

.pi-popup__eyebrow {
  margin: 0 0 12px;
}

.pi-popup__title {
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  font-weight: 400;
  font-size: clamp(30px, 4.2vw, 41px);
  line-height: 1.03;
  letter-spacing: -0.035em;
}

.pi-popup__title em {
  font-style: italic;
}

.pi-popup__body {
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.7;
  color: #65675f;
}

.pi-popup__form {
  display: flex;
  gap: 8px;
  margin-top: 22px;
}

.pi-popup__form input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 12px 13px;
  border: 1px solid #c9c6b6;
  background: #fffdf8;
  font-size: 14px;
  color: var(--pi-ink);
}

.pi-popup__form input:focus {
  outline: 2px solid var(--pi-ink);
  outline-offset: -1px;
}

.pi-popup__form .btn {
  flex: none;
  padding: 0 20px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.pi-popup__done {
  margin-top: 22px;
}

.pi-popup__note {
  margin: 13px 0 0;
  font-size: 11px;
  line-height: 1.6;
  color: #83867b;
}

@media (max-width: 560px) {
  .pi-popup {
    width: calc(100vw - 24px);
  }

  .pi-popup__card {
    padding: 26px 22px 22px;
  }

  .pi-popup__figure {
    margin: -26px -22px 18px;
  }

  .pi-popup__title {
    font-size: 28px;
  }

  .pi-popup__form {
    flex-direction: column;
  }

  .pi-popup__form .btn {
    padding: 13px 18px;
  }
}

/* ------------------------------------------------------------ paypal popup */

/* A sheet of paper dropped over the page rather than an app modal: same paper,
   same hairline rule, same uppercase eyebrow as the rest of the shop. The
   PayPal button inside stays yellow on purpose — it is the one element allowed
   to break the palette, because a PayPal button that does not look like PayPal
   is worse than no express checkout at all. */

.pi-paymodal {
  width: min(404px, calc(100vw - 30px));
  max-width: none;
  max-height: calc(100vh - 30px);
  padding: 0;
  border: 0;
  margin: auto;
  background: transparent;
  color: var(--pi-ink);
  overflow: visible;
}

.pi-paymodal::backdrop {
  background: rgba(32, 33, 29, 0.52);
  backdrop-filter: blur(3px);
}

.pi-paymodal[open] {
  animation: pi-pop 0.18s ease-out;
}

@keyframes pi-pop {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.pi-paymodal__card {
  position: relative;
  padding: 26px 24px 20px;
  background: #fffdf8;
  border: 1px solid var(--pi-line);
  box-shadow: 0 30px 60px -24px rgba(32, 33, 29, 0.5);
  max-height: calc(100vh - 30px);
  overflow-y: auto;
}

.pi-paymodal__x {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 0;
  background: transparent;
  color: var(--pi-muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.pi-paymodal__x:hover,
.pi-paymodal__x:focus-visible {
  color: var(--pi-ink);
}

.pi-paymodal__eyebrow {
  margin: 0 0 7px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-paymodal__title {
  margin: 0 0 14px;
  font-size: 26px;
  line-height: 1.04;
  letter-spacing: -0.02em;
  padding-right: 28px;
}

.pi-paymodal__subject {
  margin: 0 0 10px;
  font-size: 12px;
  color: var(--pi-muted);
}

/* The price and its qualifier share one ruled band, so "each" cannot drift
   onto a line of its own and read like a second amount. */
.pi-paymodal__amount {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 7px;
  margin: 0 0 16px;
  padding: 11px 0;
  border-top: 1px solid var(--pi-line);
  border-bottom: 1px solid var(--pi-line);
}

.pi-paymodal__amount b {
  font-size: 19px;
  letter-spacing: -0.01em;
}

.pi-paymodal__amount span {
  font-size: 11.5px;
  color: var(--pi-muted);
}

/* Reserving the height means the buttons landing a beat later does not shove
   the rest of the card downwards while the shopper is reaching for them. */
.pi-paymodal__slot {
  min-height: 47px;
  transition: opacity 0.15s ease;
}

.pi-paymodal__slot.is-busy {
  opacity: 0.4;
  pointer-events: none;
}

.pi-paymodal__status {
  margin: 10px 0 0;
  min-height: 15px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--pi-muted);
}

.pi-paymodal__err {
  margin: 12px 0 0;
  padding: 9px 11px;
  font-size: 12px;
  line-height: 1.55;
  color: #7d2a12;
  background: #f7e3dc;
  border-left: 3px solid var(--pi-orange);
}

.pi-paymodal__note {
  margin: 14px 0 0;
  font-size: 11px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-paymodal__fallback {
  display: inline-block;
  margin-top: 11px;
  font-size: 11.5px;
  color: var(--pi-ink);
  text-decoration: none;
  border-bottom: 1px solid var(--pi-line);
}

.pi-paymodal__fallback:hover {
  border-bottom-color: var(--pi-ink);
}

@media (max-width: 460px) {
  .pi-paymodal__card {
    padding: 22px 17px 16px;
  }

  .pi-paymodal__title {
    font-size: 23px;
  }
}

/* --------------------------------------------------------- more payment ways */

/* The escape hatch from express checkout, drawn as text and not as a button:
   it is a second thought next to a yellow PayPal slab, and a second slab would
   read as a second way to pay immediately. It is still a submit button, so it
   carries the quantity and option chosen above — an <a> would have to rebuild
   both in JavaScript. */
.buyrow .pi-paymore {
  flex: 1 1 100%;
  /* site.css gives every button a 44px floor and a 1px lift on hover; both are
     right for a button and wrong for a line of underlined text. */
  min-height: 0 !important;
  margin: 0;
  padding: 6px 2px 2px;
  border: 0;
  background: none;
  color: var(--pi-ink);
  font-family: inherit;
  font-size: 13.5px;
  line-height: 1.5;
  letter-spacing: normal;
  text-transform: none;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  cursor: pointer;
}

.buyrow .pi-paymore:hover,
.buyrow .pi-paymore:focus-visible {
  color: var(--pi-orange);
  transform: none;
}

/* ------------------------------------------------------ payment information */

/* One boxed block on the till, the way every checkout the buyer has ever used
   puts it: a card with a heading, a list of choices, and one line explaining
   the choice that is currently made. The box is deliberate — the delivery
   fields above sit straight on the paper, so a border here is what separates
   "what we ask you" from "how you pay". */
.pi-payinfo {
  margin: 24px 0 4px;
  padding: 20px 22px 8px;
  border: 1px solid var(--pi-line);
  background: var(--pi-white, #fffdf8);
}

.pi-payinfo__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}

/* Same face and size as "Delivery details" and "Your order" — .pi-formhead —
   so the three headings on the till read as one family. Only the margin is
   different: this one is inside a flex row with the SECURE tag, not above a
   list of fields. */
.pi-payinfo__head .pi-formhead {
  margin: 0;
}

.pi-payinfo__secure {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
  white-space: nowrap;
}

.pi-payinfo__secure span {
  color: var(--pi-orange);
}

.pi-payinfo__opts {
  margin-top: 6px;
}

.pi-payopt {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 0;
  border-top: 1px solid var(--pi-line);
  cursor: pointer;
  font-size: 14px;
}

.pi-payinfo__opts .pi-payopt:first-child {
  border-top: 0;
}

/* A radio drawn rather than borrowed: the native one is blue on some systems
   and grey on others, and this page has exactly one ink colour for "chosen". */
/* site.css forces `border: 1px solid … !important`, `border-radius: 0 !important`
   and `min-height: 44px` on every input — which turns this radio into a tall
   rectangle. Three !importants to undo one; the alternative was editing the
   design file, and that file is the design as drawn. */
.pi-payopt input[type='radio'] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  min-height: 0 !important;
  margin: 0;
  padding: 0;
  border: 1px solid #bcbcb0 !important;
  border-radius: 50% !important;
  background: #fff !important;
  display: grid;
  place-content: center;
  cursor: pointer;
}

.pi-payopt input[type='radio']::after {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--pi-ink);
  transform: scale(0);
  transition: transform 0.12s ease;
}

.pi-payopt input[type='radio']:checked {
  border-color: var(--pi-ink) !important;
}

.pi-payopt input[type='radio']:checked::after {
  transform: scale(1);
}

.pi-payopt input[type='radio']:focus-visible {
  outline: 2px solid var(--pi-ink);
  outline-offset: 2px;
}

.pi-payopt:has(input:checked) .pi-payopt__name {
  font-weight: 600;
}

.pi-payinfo__panel {
  padding: 2px 0 12px;
}

/* "Enter your email address above to continue." — the reference checkout's grey
   bar, and the same promise here: nothing else on this panel is worth reading
   until there is an address to bill. The field itself is further up the page,
   so this is a signpost, not an input, and it is not focusable on purpose. */
.pi-payinfo__ghost {
  margin: 0 0 10px;
  padding: 12px 14px;
  background: #f0efe7;
  color: #9a9a8f;
  font-size: 13.5px;
  line-height: 1.4;
}

.pi-payinfo__note {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--pi-muted);
}

@media (max-width: 520px) {
  .pi-payinfo {
    padding: 18px 16px 6px;
  }
}

/* --------------------------------------------------------- card on the till */

/* The card form the reference checkout shows under "Credit card". The boxes
   are drawn by us and filled by PayPal's iframes, so the shape is set here and
   only the type inside them comes from the SDK. Flat borders and square
   corners on purpose: this is the same paper as the delivery fields above, and
   a rounded PayPal widget in the middle of it would look borrowed. */
.pi-cardform {
  margin: 2px 0 0;
  padding: 16px 16px 14px;
  border: 1px solid var(--pi-line);
  background: #f8f7f0;
}

.pi-cardform__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.pi-cardform__label {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-cardbrands {
  display: flex;
  align-items: center;
  gap: 4px;
}

.pi-cardbrand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  width: 34px;
  height: 22px;
  border: 1px solid #dcdcd2;
  background: #fff;
  border-radius: 3px;
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1;
}

.pi-cardbrand--visa {
  color: #1a1f71;
}

.pi-cardbrand--amex {
  color: #006fcf;
  font-size: 7px;
}

/* Two circles, the way the mark is built — a bitmap would need a second HTTP
   request for four pixels of colour. */
.pi-cardbrand--mc {
  position: relative;
}

.pi-cardbrand--mc i {
  position: absolute;
  top: 50%;
  width: 12px;
  height: 12px;
  margin-top: -6px;
  border-radius: 50%;
}

.pi-cardbrand--mc i:first-child {
  left: 8px;
  background: #eb001b;
  opacity: 0.85;
}

.pi-cardbrand--mc i:last-child {
  right: 8px;
  background: #f79e1b;
  opacity: 0.85;
}

.pi-cardbrand--more {
  width: auto;
  padding: 0 6px;
  color: var(--pi-muted);
  font-weight: 500;
  background: #f2f1e9;
}

.pi-cardrow {
  margin-bottom: 10px;
}

.pi-cardrow--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

/* PayPal injects an iframe here and sizes it to its own content; the box takes
   that height instead of fighting it, and the icon sits above the frame on the
   right. A fixed height would clip the frame and let the field below overlap
   it — which is exactly what happened the first time round. */
.pi-cardfield {
  position: relative;
  min-height: 46px;
  border: 1px solid var(--pi-line);
  background: #fff;
}

.pi-cardfield iframe {
  width: 100% !important;
  display: block;
  border: 0;
}

.pi-cardfield__icon {
  position: absolute;
  top: 50%;
  right: 13px;
  z-index: 2;
  display: none;
  transform: translateY(-50%);
  color: #9a9a8f;
  font-size: 12px;
  line-height: 1;
  pointer-events: none;
}

.pi-cardfield__icon--lock svg {
  display: block;
}

/* The icons only make sense once the frame is there — before that the box is
   empty and a lone padlock floats in nothing. */
.pi-cardform[data-card-ready='1'] .pi-cardfield__icon {
  display: block;
}

/* PayPal sets the frame's width inline; border-box keeps that width inside the
   hairline instead of spilling one pixel over it. */
.pi-cardform[data-card-ready='1'] .pi-cardfield iframe {
  box-sizing: border-box;
}

.pi-cardcheck {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 12px 0 0;
  font-size: 13.5px;
  line-height: 1.45;
  cursor: pointer;
}

.pi-cardcheck input[type='checkbox'] {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  min-height: 0 !important;
  margin: 2px 0 0;
  padding: 0;
  accent-color: var(--pi-ink);
}

.pi-cardbill {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #e4e3d8;
}

.pi-cardbill[hidden] {
  display: none;
}

.pi-cardbill__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 10px;
}

.pi-cardbill .pi-field {
  margin-bottom: 10px;
}

.pi-cardform__err {
  margin: 10px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: #b3261e;
}

.pi-cardform__err[hidden] {
  display: none;
}

/* What the panel says when there is no form to show: no JavaScript, PayPal
   refusing hosted fields, or a blocked script. It has to read as a normal
   instruction, not as an error — the payment still works, one window later. */
.pi-cardform__fallback {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--pi-muted);
}

/* One switch, two states: the empty boxes and the sentence that replaces them
   are never on screen together. */
.pi-cardform[data-card-ready='0'] .pi-cardrow,
.pi-cardform[data-card-ready='0'] .pi-cardcheck,
.pi-cardform[data-card-ready='0'] .pi-cardbill {
  display: none;
}

.pi-cardform[data-card-ready='1'] .pi-cardform__fallback {
  display: none;
}

@media (max-width: 520px) {
  .pi-cardform {
    padding: 14px 12px 12px;
  }

  /* Expiry and security code share a row on desktop; stacked here they keep
     the 10px gap, or two separate boxes end up sharing one border line and
     reading as a single tall field. */
  .pi-cardrow--split {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .pi-cardbill__row {
    grid-template-columns: 1fr;
  }
}


/* ------------------------------------------------------------ apple / google */

/* A wallet radio that turned out to be unusable is removed by the script;
   without this, `hidden` loses to the flex layout above. */
.pi-payopt[hidden] {
  display: none;
}

.pi-wallet {
  margin: 4px 0 2px;
}

.pi-wallet[hidden] {
  display: none;
}

/* Apple draws this button itself: `-apple-pay-button` is the official mark in
   the official black, and it is only ever shown in a browser that answered
   "yes, I can pay". The rest of the rule is the fallback for the impossible
   case where that appearance is ignored — a black bar with the word on it beats
   an invisible button. */
.pi-wallet__apple {
  display: block;
  width: 100%;
  height: 46px;
  min-height: 0 !important;
  padding: 0;
  border: 0 !important;
  border-radius: 0 !important;
  background: #000;
  color: #fff;
  font: inherit;
  font-size: 16px;
  cursor: pointer;
  -webkit-appearance: -apple-pay-button;
  -apple-pay-button-style: black;
  -apple-pay-button-type: buy;
}

.pi-wallet__google {
  width: 100%;
}

/* Google's button arrives with its own inline styles; the box only has to make
   sure it fills the column like every other control on this page. */
.pi-wallet__google > div,
.pi-wallet__google > button {
  width: 100%;
}

.pi-wallet__status {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: #b3261e;
}

.pi-wallet__status:empty {
  display: none;
}

/* Shown when the wallet cannot be used here — no JavaScript, or a browser and
   device that cannot pay with it. Same weight as the note it stands in for. */
.pi-wallet__fallback {
  margin: 2px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-wallet__fallback[hidden] {
  display: none;
}

/* What the buyer said they would pay with, in the order's side panel. Small
   and quiet: it answers "how did I pay" for the one person who scrolls back to
   this page a week later, and it is not the headline of the order. */
.pi-ordermeta {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: baseline;
  margin: 0 0 10px;
  font-size: 13px;
}

.pi-ordermeta span {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
}



/* ==========================================================================
   Product reviews

   Three bands, in the order a shopper reads them: what the pile of reviews
   adds up to, what people actually wrote, and the form. The snapshot strip is
   a table without table markup — label, bar, count — because its columns have
   to line up across five rows and nothing else on the page does.

   The stars are two stacked rows with the coloured one clipped by width. It is
   the only honest way to draw 4.6, and it degrades to five grey stars with no
   JavaScript at all.
   ========================================================================== */

.pi-reviews {
  padding: 64px 0 76px;
  /* The header is sticky; an anchor jump must not land the heading under it. */
  scroll-margin-top: 96px;
}

.pi-reviewform {
  scroll-margin-top: 96px;
}

.pi-reviews__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  border-top: 1px solid var(--pi-line);
  padding-top: 26px;
}

.pi-reviews__head h2 {
  margin: 8px 0 0;
}

.pi-reviews__head h2 em {
  font-style: italic;
}

.pi-reviews__count {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pi-muted);
  white-space: nowrap;
  padding-bottom: 6px;
}

/* ------------------------------------------------------------------ stars */

.pi-stars {
  position: relative;
  display: inline-block;
  line-height: 0;
  vertical-align: middle;
}

.pi-stars__layer {
  display: flex;
  gap: 2px;
}

.pi-stars__layer--off {
  color: #d8d5c9;
}

.pi-stars__layer--on {
  position: absolute;
  left: 0;
  top: 0;
  overflow: hidden;
  color: var(--pi-orange);
}

.pi-stars svg {
  display: block;
  flex: 0 0 auto;
  fill: currentColor;
}

/* The line under the product title. A link, because it does something. */
.pi-ratingline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: -4px 0 14px;
  font-size: 12px;
  color: var(--pi-muted);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}

.pi-ratingline b {
  font-size: 13px;
  color: var(--pi-ink);
}

.pi-ratingline:hover {
  border-bottom-color: var(--pi-ink);
}

/* ------------------------------------------------------------ rating strip */

.pi-rating {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr 1fr;
  border: 1px solid var(--pi-line);
  background: var(--pi-white, #fffdf8);
  margin: 28px 0 0;
}

.pi-rating--empty {
  grid-template-columns: 1.6fr 1fr;
}

.pi-rating__cell {
  padding: 22px 24px;
  min-width: 0;
}

.pi-rating__cell + .pi-rating__cell {
  border-left: 1px solid var(--pi-line);
}

.pi-rating--empty .pi-rating__cell + .pi-rating__cell {
  border-left: 1px solid var(--pi-line);
}

.pi-rating__eyebrow {
  margin: 0 0 12px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-rating__lede {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--pi-muted);
  max-width: 46ch;
}

/* --------------------------------------------------------------- histogram */

.pi-bars {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 7px;
}

.pi-bars__row {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) 28px;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--pi-muted);
}

.pi-bars__track {
  height: 8px;
  background: #e7e4d9;
  overflow: hidden;
}

.pi-bars__track i {
  display: block;
  height: 100%;
  background: var(--pi-orange);
}

.pi-bars__count {
  text-align: right;
  font-size: 11px;
  font-weight: 600;
  color: var(--pi-ink);
}

/* ------------------------------------------------------------------- score */

.pi-score {
  display: flex;
  align-items: center;
  gap: 14px;
}

.pi-score strong {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-size: 54px;
  line-height: 0.9;
  letter-spacing: -0.05em;
}

.pi-score__meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 11px;
  color: var(--pi-muted);
}

.pi-recommend {
  margin: 16px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--pi-muted);
}

.pi-recommend b {
  color: var(--pi-ink);
}

/* ------------------------------------------------------------- quick rating */

.pi-quick {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.pi-quick__star {
  width: 42px;
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid #e5e2d6;
  background: transparent;
  color: #b9b5a5;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.pi-quick__star svg {
  fill: currentColor;
}

.pi-quick__star:hover,
.pi-quick__star:focus-visible {
  color: var(--pi-orange);
  border-color: var(--pi-orange);
  background: rgba(232, 117, 63, 0.07);
  outline: none;
}

/* Set by the script when one of these is pressed, so the choice stays visible
   while the page scrolls down to the form. Without JavaScript they are simply
   a jump link — the form has its own radio picker. */
.pi-quick__star.is-filled {
  color: var(--pi-orange);
  border-color: var(--pi-orange);
}

.pi-quick__hint {
  margin: 12px 0 0;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--pi-muted);
  max-width: 34ch;
}

/* ---------------------------------------------------------------- summary */

.pi-resummary {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 12px;
  padding: 22px 0;
  border-bottom: 1px solid var(--pi-line);
}

.pi-resummary__mark {
  color: var(--pi-orange);
  font-size: 13px;
  line-height: 1.6;
}

.pi-resummary__label {
  margin: 0 0 6px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-resummary div > p:last-child {
  margin: 0;
  font-size: 14px;
  line-height: 1.75;
  color: #4c4f47;
  max-width: 82ch;
}

/* ------------------------------------------------------------- review list */

.pi-reviewlist {
  list-style: none;
  margin: 0;
  padding: 0;
}

.pi-review {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 18px;
  padding: 26px 0;
  border-bottom: 1px solid var(--pi-line);
}

.pi-review__avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--pi-ink);
  color: var(--pi-paper);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  letter-spacing: 0.06em;
}

.pi-review__main {
  min-width: 0;
  /* A 1100px line of body copy is a keyboard-width paragraph. Reviews are
     read, not scanned, so the measure stays at a book's width. */
  max-width: 78ch;
}

.pi-review__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.pi-review__head strong {
  font-size: 14px;
}

/* The date follows the name instead of being pushed to the far right: at 78ch
   of review text a right-aligned date floated in the middle of nowhere. */
.pi-review__head time {
  font-size: 11px;
  color: var(--pi-muted);
  padding-left: 10px;
  border-left: 1px solid var(--pi-line);
}

.pi-badge {
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1px solid var(--pi-line);
  padding: 3px 7px;
  color: var(--pi-muted);
  white-space: nowrap;
}

.pi-review__stars {
  margin-top: 7px;
}

.pi-review h3 {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 400;
  font-size: 20px;
  letter-spacing: -0.02em;
  margin: 10px 0 6px;
}

.pi-review__copy p {
  margin: 0 0 8px;
  font-size: 14px;
  line-height: 1.75;
  color: #4c4f47;
}

.pi-review__copy p:last-child {
  margin-bottom: 0;
}

.pi-review__helpful {
  margin: 8px 0 0;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--pi-muted);
}

.pi-review__reply {
  margin-top: 14px;
  border-left: 2px solid var(--pi-orange);
  padding: 2px 0 2px 14px;
}

.pi-review__reply span {
  display: block;
  margin-bottom: 5px;
  font-size: 9.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-review__reply p {
  margin: 0;
  font-size: 13px;
  line-height: 1.7;
  color: #4c4f47;
}

/* ------------------------------------------------------------------- form */

.pi-reviewform {
  position: relative;
  margin: 34px 0 0;
  border: 1px solid var(--pi-ink);
  background: var(--pi-white, #fffdf8);
  padding: 26px;
}

.pi-reviewform__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}

.pi-reviewform__head h3 {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 27px;
  font-weight: 400;
  letter-spacing: -0.03em;
  margin: 0 0 6px;
}

.pi-reviewform__head p {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--pi-muted);
  max-width: 54ch;
}

.pi-reviewform__mark {
  font-size: 20px;
  line-height: 1;
  color: var(--pi-orange);
}

.pi-reviewform__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 18px;
}

.pi-reviewform .pi-field--wide {
  grid-column: 1 / -1;
}

.pi-reviewform .pi-field--stars {
  grid-column: 1 / -1;
  border: 0;
  padding: 0;
  margin: 0 0 16px;
  min-width: 0;
}

.pi-reviewform .pi-field legend {
  display: block;
  padding: 0;
  margin-bottom: 7px;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

/* Radios are excluded: the picker positions its own inputs, and `width:100%`
   on an absolutely positioned radio resolves against the viewport — a 1440px
   invisible radio is a horizontal scrollbar nobody can explain. */
.pi-reviewform .pi-field input:not([type='radio']),
.pi-reviewform .pi-field textarea {
  width: 100%;
  padding: 12px 14px;
  background: var(--pi-paper);
  border: 1px solid var(--pi-line);
  border-radius: 0;
  font-size: 15px;
  font-family: inherit;
  color: var(--pi-ink);
}

.pi-reviewform .pi-field textarea {
  resize: vertical;
  min-height: 104px;
  line-height: 1.6;
}

.pi-reviewform .pi-field input:not([type='radio']):focus,
.pi-reviewform .pi-field textarea:focus {
  outline: 2px solid var(--pi-ink);
  outline-offset: -1px;
}

/* A rejected field looks rejected. These rules sit after :focus on purpose —
   the failing box gets focused on arrival, and a black focus ring over a red
   border reads as "nothing is wrong". */
.pi-reviewform .pi-field.is-error input:not([type='radio']),
.pi-reviewform .pi-field.is-error textarea {
  border-color: #b3261e;
  background: rgba(179, 38, 30, 0.04);
}

.pi-reviewform .pi-field.is-error input:not([type='radio']):focus,
.pi-reviewform .pi-field.is-error textarea:focus {
  outline-color: #b3261e;
}

.pi-field__err {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: #b3261e;
  max-width: 60ch;
}

.pi-field__opt {
  text-transform: none;
  letter-spacing: 0;
  color: var(--pi-muted);
  opacity: 0.75;
}

/* The picker is five radios laid out right-to-left so that "everything after
   the checked one" means "the stars below it" — the only sibling direction
   CSS can select. Reversing the flex order puts them back in 1..5 on screen. */
.pi-starpick {
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  gap: 4px;
}

.pi-starpick input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.pi-starpick label {
  font-size: 30px;
  line-height: 1;
  color: #d2cfc2;
  cursor: pointer;
  padding: 0 2px;
  transition: color 0.12s;
}

.pi-starpick input:checked + label,
.pi-starpick input:checked ~ label {
  color: var(--pi-orange);
}

/* While the pointer is inside the picker the saved choice must stop showing,
   otherwise hovering 3 on a 5-star review leaves 4 and 5 lit. */
.pi-starpick:hover label {
  color: #d2cfc2;
}

.pi-starpick label:hover,
.pi-starpick label:hover ~ label {
  color: var(--pi-orange);
}

.pi-starpick input:focus-visible + label {
  outline: 2px solid var(--pi-ink);
  outline-offset: 2px;
}

/* Clipped in place rather than parked at left:-9999px. An off-canvas box is a
   wide element in the layout tree, and on a phone it is one stray horizontal
   scroll away. */
.pi-hp {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.pi-reviewform__foot {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.pi-reviewform__foot .btn {
  padding: 14px 28px;
}

.pi-reviewform__foot .pi-quick__hint {
  margin: 0;
  max-width: 44ch;
}

/* ---------------------------------------------------------------- notices */

.pi-reviewnotice {
  margin: 22px 0 0;
  padding: 13px 16px;
  font-size: 13px;
  line-height: 1.6;
  border-left: 3px solid var(--pi-ink);
  background: rgba(32, 33, 29, 0.05);
}

.pi-reviewnotice--ok {
  border-left-color: #3f6b45;
  background: rgba(63, 107, 69, 0.08);
}

.pi-reviewnotice--bad {
  border-left-color: #b3261e;
  background: rgba(179, 38, 30, 0.07);
}

/* --------------------------------------------------------------- responsive */

@media (max-width: 900px) {
  .pi-rating,
  .pi-rating--empty {
    grid-template-columns: 1fr 1fr;
  }

  .pi-rating__cell--write {
    grid-column: 1 / -1;
    border-left: 0 !important;
    border-top: 1px solid var(--pi-line);
  }

  .pi-rating__cell--score {
    border-right: 0;
  }
}

@media (max-width: 620px) {
  .pi-reviews {
    padding: 44px 0 52px;
  }

  .pi-reviews__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .pi-reviews__count {
    padding-bottom: 0;
  }

  .pi-rating,
  .pi-rating--empty {
    grid-template-columns: 1fr;
  }

  .pi-rating__cell {
    padding: 18px 18px;
  }

  .pi-rating__cell + .pi-rating__cell,
  .pi-rating__cell--write {
    border-left: 0 !important;
    border-top: 1px solid var(--pi-line);
  }

  .pi-score strong {
    font-size: 46px;
  }

  .pi-review {
    grid-template-columns: 36px minmax(0, 1fr);
    gap: 12px;
    padding: 22px 0;
  }

  .pi-review__avatar {
    width: 36px;
    height: 36px;
    font-size: 11px;
  }

  .pi-review__head time {
    border-left: 0;
    padding-left: 0;
  }

  .pi-reviewform {
    padding: 20px 16px;
  }

  .pi-reviewform__grid {
    grid-template-columns: 1fr;
  }

  .pi-reviewform__head h3 {
    font-size: 23px;
  }

  .pi-reviewform__foot {
    align-items: flex-start;
    flex-direction: column;
    gap: 10px;
  }

  .pi-reviewform__foot .btn {
    width: 100%;
  }
}

/* Between a tablet and a desktop the rail beside the columns costs more than
   it gives: 200px of a 900px sheet leaves the columns 239px each, one of them
   wraps under the others, and the sheet grows 150px taller. The rail becomes a
   line above the columns at that size, and the columns get the whole width back.
   1220, not 1040: the shop menu now has four columns, and four fixed 208px
   tracks need 1186px of panel. Below that the tracks would overflow the panel's
   own max-width and the last column would hang outside the sheet. */
@media (max-width: 1220px) {
  .navdrop__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
    padding-top: 22px;
  }

  /* Fixed tracks would push a three-column menu past the window here; the
     columns go fluid instead, and the sheet's max-width stops them. */
  .navdrop__cols {
    --gap: 22px;
    grid-template-columns: repeat(var(--tracks, 2), minmax(0, var(--track)));
    column-gap: var(--gap);
  }

  .navdrop__rail {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 14px;
    padding: 0 0 14px;
    border-right: 0;
    border-bottom: 1px solid var(--pi-line);
    /* The sentence above the columns must not decide the sheet's width here:
       one menu's note is longer than another's, and the sheet's right edge
       would jump 60px between them. With its intrinsic width taken out of the
       count, all three sheets are as wide as their columns, and the note wraps
       inside whatever that is. */
    contain: inline-size;
  }

  /* Read as two lines instead of one: section name and the way out on the
     first, the sentence across the full width under them. Tried on one line
     first, and the sentence either orphaned a word or pushed the link down to
     a line of its own — the layout changed shape with the length of a
     sentence the owner writes freely. */
  .navdrop__note {
    order: 3;
    flex: 1 0 100%;
    max-width: 62ch;
    font-size: 15px;
  }

  .navdrop__all {
    order: 2;
    margin-top: 0;
    margin-left: auto;
  }
}

/* The star is drawn for a 12px bar label. In the drawer the same entry is set
   in 21px serif, where a 9px glyph reads as a speck rather than a mark. */
.mobile-nav .navlink__mark {
  font-size: 12px;
  transform: translateY(-2px);
  margin-right: 2px;
}

/* ------------------------------------------------- article shelves (cats) */

/* The strip under the journal heading. One row of small caps labels, each with
   a count, because "which shelf has anything on it" should be answerable
   without clicking four dead links. Wraps rather than scrolls: a horizontal
   scroll area hides the last shelves behind a gesture nobody performs. */
.pi-catnav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 30px;
  padding-top: 20px;
  border-top: 1px solid var(--pi-line);
}

.pi-catnav__item {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  padding: 7px 12px;
  border: 1px solid var(--pi-line);
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--pi-muted);
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.pi-catnav__item span {
  font-size: 10px;
  letter-spacing: 0.04em;
  opacity: 0.55;
}

.pi-catnav__item:hover {
  border-color: var(--pi-ink);
  color: var(--pi-ink);
}

.pi-catnav__item.on {
  background: var(--pi-ink);
  border-color: var(--pi-ink);
  color: var(--pi-paper);
}

/* The same class does two jobs: "back to all notes" above an archive, and the
   category label inside an article's eyebrow. Same intent, same treatment — a
   plain underline that does not shout over the heading next to it. */
.pi-catnav__back {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.pi-catnav__back:hover {
  color: var(--pi-ink);
}

@media (max-width: 620px) {
  .pi-catnav {
    margin-top: 24px;
    padding-top: 16px;
    gap: 6px;
  }

  .pi-catnav__item {
    padding: 7px 10px;
    /* 10px was one step too small to read as a label on a phone; the extra
       pixel costs nothing because the row wraps anyway. */
    font-size: 11px;
  }
}

/* ------------------------------------------------------- buy it together */

/* The group offer sits under the buy buttons, on paper rather than on the page:
   it is a small offer, not a second product page, and a panel makes the four
   rows read as one thing instead of as three more items for sale. */
.pi-bundle {
  margin: 24px 0 6px;
  padding: 18px 18px 16px;
  border: 1px solid var(--pi-line);
  background: var(--pi-paper);
}

.pi-bundle__head .eyebrow {
  margin: 0 0 6px;
  font-size: 10px;
  letter-spacing: 0.16em;
}

.pi-bundle__title {
  margin: 0 0 6px;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 21px;
  line-height: 1.22;
  letter-spacing: -0.03em;
  color: var(--pi-ink);
}

.pi-bundle__note {
  margin: 0 0 4px;
  max-width: 46ch;
  font-size: 12px;
  line-height: 1.5;
  color: var(--pi-muted);
}

.pi-bundle__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.pi-bundle__item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 0;
  border-bottom: 1px dotted var(--pi-line);
}

.pi-bundle__item:last-child {
  border-bottom: 0;
}

/* The main row has no checkbox, so it is indented by exactly the width of one
   plus the gap: without that the four thumbnails step out of line and the
   group reads as a list that lost its first box. */
.pi-bundle__item--main {
  padding-left: 25px;
}

.pi-bundle__pick {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

.pi-bundle__pick input[type='checkbox'] {
  flex: none;
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: var(--pi-ink);
  cursor: pointer;
}

.pi-bundle__thumb {
  flex: none;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  overflow: hidden;
  background: #eceade;
}

.pi-bundle__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pi-bundle__glyph {
  font-size: 20px;
  color: var(--pi-ink);
}

.pi-bundle__copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.pi-bundle__copy b {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--pi-ink);
}

.pi-bundle__copy small {
  font-size: 11px;
  color: var(--pi-muted);
}

.pi-bundle__price {
  margin-left: auto;
  flex: none;
  padding-left: 10px;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--pi-ink);
}

.pi-bundle__foot {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.pi-bundle__sum {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}

.pi-bundle__sum s {
  font-size: 12.5px;
  color: var(--pi-muted);
}

.pi-bundle__sum strong {
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--pi-ink);
}

.pi-bundle__sum span {
  flex-basis: 100%;
  font-size: 11.5px;
  color: var(--pi-muted);
}

.pi-bundle__sum span b {
  font-weight: 600;
  color: var(--pi-orange);
}

/* No group, no saving: either nothing is ticked or only part of the offer is,
   and in both cases the price is the plain sum. Printing "$46.75 was $46.75"
   and a "save $0.00" line would be noise dressed as an offer. */
.pi-bundle__sum.is-single s,
.pi-bundle__sum.is-single span {
  display: none;
}

/* The button takes the whole row. Right-aligning it left a pocket of empty
   paper between the total and the one thing the block is asking for, and on a
   narrow panel it wrapped anyway — so it may as well read as the main action
   it is, matching the bag button directly above. */
.pi-bundle__foot .btn {
  flex: 1 1 100%;
  margin-left: 0;
  white-space: normal;
}

@media (max-width: 560px) {
  .pi-bundle {
    padding: 16px 14px 14px;
  }

  .pi-bundle__item--main {
    padding-left: 25px;
  }

  .pi-bundle__foot .btn {
    margin-left: 0;
    width: 100%;
  }
}

/* ==========================================================================
   Accounts and order lookup.

   Two new pages share one skeleton: a single column of fields on the left and
   a quiet column of reassurance on the right. The account page reuses that
   same grid but turns the right column into the editable parts, so "my
   details" sits where "what you get" sat on the way in — the eye does not have
   to relearn the page.
   ========================================================================== */

.pi-auth {
  padding-bottom: 90px;
}

.pi-auth__lead {
  max-width: 640px;
  font-size: 17px;
  line-height: 1.65;
  color: var(--pi-muted);
  margin: 0 0 42px;
}

.pi-auth__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
  border-top: 1px solid var(--pi-line);
  padding-top: 38px;
}

.pi-auth__form {
  max-width: none;
  margin: 0;
}

.pi-auth__form .btn {
  width: 100%;
  margin-top: 8px;
}

/* The aside is a margin note, not a second form: a hairline instead of a card
   keeps it from competing with the thing the page is actually asking for. */
.pi-auth__aside {
  border-left: 1px solid var(--pi-line);
  padding-left: clamp(20px, 3vw, 40px);
}

.pi-auth__aside .pi-formhead {
  font-size: 19px;
  margin-bottom: 14px;
}

.pi-auth__list {
  list-style: none;
  margin: 0 0 4px;
  padding: 0;
}

.pi-auth__list li {
  font-size: 14px;
  line-height: 1.65;
  color: var(--pi-muted);
  padding-bottom: 16px;
}

.pi-auth__list strong {
  display: block;
  color: var(--pi-ink);
  font-weight: 400;
  font-family: Georgia, serif;
  font-size: 16px;
  letter-spacing: -0.02em;
  margin-bottom: 2px;
}

.pi-auth__list a {
  white-space: nowrap;
}

/* A field's footnote. Sits under the input rather than in the label, because
   "at least 8 characters" is a rule about the answer, not about the question. */
.pi-note {
  display: block;
  font-size: 12px;
  line-height: 1.55;
  color: var(--pi-muted);
  margin-top: 6px;
}

.pi-auth__form .pi-alert {
  margin: 0 0 20px;
}

/* ---------------------------------------------------------- account page */

.pi-account__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--pi-line);
  border-bottom: 1px solid var(--pi-line);
  margin: 4px 0 46px;
}

.pi-account__stats > div {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px 0;
}

.pi-account__stats > div + div {
  border-left: 1px solid var(--pi-line);
  padding-left: 24px;
}

.pi-account__stats span {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pi-muted);
}

.pi-account__stats strong {
  font-family: Georgia, serif;
  font-size: 30px;
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1;
}

.pi-account__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr);
  gap: clamp(28px, 5vw, 64px);
  align-items: start;
}

.pi-orderlist {
  display: grid;
  gap: 14px;
}

.pi-orderrow {
  border: 1px solid var(--pi-line);
  background: var(--pi-white, #fffdf8);
  padding: 18px 20px;
}

.pi-orderrow__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}

.pi-orderrow__ref {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.pi-orderrow__date {
  display: block;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--pi-muted);
  margin-top: 4px;
}

.pi-orderrow .pi-status {
  margin: 0;
  padding: 6px 9px;
  font-size: 10px;
}

.pi-orderrow__items {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  font-size: 14px;
  line-height: 1.5;
  color: #3a3b34;
}

.pi-orderrow__items li {
  padding: 2px 0;
}

.pi-orderrow__qty {
  color: var(--pi-muted);
  font-size: 12px;
  margin-right: 4px;
}

.pi-orderrow__label,
.pi-orderrow__more {
  color: var(--pi-muted);
}

.pi-orderrow__more {
  font-size: 12px;
  font-style: italic;
}

.pi-orderrow__track {
  font-size: 12px;
  color: var(--pi-muted);
  margin: 12px 0 0;
}

.pi-orderrow__foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 16px;
  padding-top: 13px;
  border-top: 1px dashed var(--pi-line);
}

.pi-orderrow__foot strong {
  font-family: Georgia, serif;
  font-size: 17px;
  font-weight: 400;
  letter-spacing: -0.02em;
}

.pi-panel {
  border-top: 1px solid var(--pi-line);
  padding: 26px 0 6px;
}

.pi-panel:first-child {
  border-top: 0;
  padding-top: 0;
}

.pi-panel .pi-formhead {
  font-size: 19px;
  margin-bottom: 14px;
}

.pi-panel .btn {
  width: 100%;
  margin-top: 6px;
}

.pi-panel--plain {
  padding-bottom: 0;
}

.pi-panel--plain .pi-note {
  margin: 0 0 10px;
}

/* An empty state is a sentence and two ways out — not an illustration of a
   sad box. */
.pi-empty {
  border: 1px dashed var(--pi-line);
  padding: 30px;
}

.pi-empty p {
  margin: 0 0 10px;
  font-size: 15px;
  line-height: 1.6;
}

.pi-empty .actions {
  margin-top: 20px;
}

@media (max-width: 900px) {
  .pi-auth__grid,
  .pi-account__grid {
    grid-template-columns: 1fr;
  }

  .pi-auth__aside {
    border-left: 0;
    border-top: 1px solid var(--pi-line);
    padding: 26px 0 0;
  }

  .pi-account__side {
    order: 2;
  }
}

@media (max-width: 600px) {
  /* The drawer carries both of these on a phone. Three text links beside a
     76px logo is where a header starts to wrap. */
  .navaccount {
    display: none;
  }

  .pi-auth {
    padding-bottom: 60px;
  }

  .pi-auth__lead {
    font-size: 16px;
    margin-bottom: 30px;
  }

  .pi-account__stats > div {
    padding: 16px 0;
  }

  .pi-account__stats > div + div {
    padding-left: 14px;
  }

  .pi-account__stats strong {
    font-size: 22px;
  }

  .pi-orderrow {
    padding: 16px;
  }

  .pi-account__grid {
    gap: 34px;
  }
}

/* The guest-order note under the list: a panel, not a card, so it reads as the
   end of the orders column rather than as another order. */
.pi-panel--foot {
  margin-top: 36px;
  border-top: 1px solid var(--pi-line);
  padding: 26px 0 0;
}

.pi-panel--foot .pi-note {
  max-width: 46ch;
}

.pi-panel__link {
  margin: 16px 0 0;
}

.pi-note--tight {
  margin: -4px 0 18px;
  max-width: 60ch;
}

/* ------------------------------------------------------------ reset steps */

/* The confirmation replaces the form, so the three "where to look next" steps
   carry the weight a button would. Numbered rather than bulleted: this is a
   short procedure, and the numbers say "do them in this order". */
.pi-auth__steps {
  counter-reset: step;
  list-style: none;
  margin: 0 0 30px;
  padding: 0;
}

.pi-auth__steps li {
  position: relative;
  counter-increment: step;
  padding: 0 0 20px 38px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--pi-muted);
}

.pi-auth__steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 1px;
  width: 23px;
  height: 23px;
  display: grid;
  place-items: center;
  border: 1px solid var(--pi-line);
  border-radius: 50%;
  font-family: Georgia, serif;
  font-size: 12px;
  color: var(--pi-ink);
}

.pi-auth__steps strong {
  display: block;
  color: var(--pi-ink);
  font-family: Georgia, serif;
  font-size: 16px;
  font-weight: 400;
  letter-spacing: -0.02em;
  margin-bottom: 2px;
}

/* The static confirmation column has no form, but it still sits in the grid
   at the form's width — a full-bleed paragraph next to a hairline aside would
   read as a caption, not as the page's main answer. */
.pi-auth__form > .btn + .pi-hint {
  margin-top: 12px;
}
