/* The Ceramic Lookbook — printed-ephemera design language.
   Paper stock #F3F1EC, card stock #FAF8F3, ink #262623, stamp red #C05A38. */

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: #F3F1EC;
}

body {
  cursor: url('../cursor.png') 8 8, auto;
  font-family: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  -webkit-font-smoothing: antialiased;
}

/* Every panel here is shown and hidden with the hidden attribute, and the
   rule behind it is a user-agent one — so any author display rule on the same
   element silently outranks it and the thing never goes away. */
[hidden] { display: none !important; }

a { color: #262623; }
a:hover { color: #C05A38; }
::selection { background: #C05A38; color: #F3F1EC; }

@keyframes fadein { from { opacity: 0 } to { opacity: 1 } }
@keyframes cardin {
  from { opacity: 0; transform: translateY(16px) rotate(-1.4deg) }
  to   { opacity: 1; transform: translateY(0) rotate(-1.4deg) }
}
@keyframes cardin2 {
  from { opacity: 0; transform: translateY(16px) }
  to   { opacity: 1; transform: translateY(0) }
}

.lookbook {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: #F3F1EC;
}

#field {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
}

/* The modules float over the field. #ui carries a single scale transform so
   they hold their proportions on short viewports; pointer events are handed
   back module by module. */
#ui {
  position: fixed;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  z-index: 10;
  pointer-events: none;
}

.module {
  pointer-events: auto;
  position: fixed;
  z-index: 10;
  box-sizing: border-box;
  background: #FAF8F3;
  border: 1px solid #D8D4CB;
  box-shadow: 0 12px 30px rgba(38, 38, 35, 0.14);
}

#catPanel { transition: top .25s ease; }

.tab {
  flex: 1;
  text-align: center;
  padding: 11px 4px;
  font-size: 8.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #928F86;
}
.tab.on {
  color: #262623;
  box-shadow: inset 0 -2px 0 #C05A38;
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px 14px;
  gap: 8px;
}
.row .count {
  font-size: 9px;
  letter-spacing: 0.08em;
  color: #928F86;
}
.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex: none;
  border: 1px solid #D8D4CB;
}
.dot.on {
  background: #C05A38;
  border-color: #C05A38;
}

/* A tear wants two pieces of paper, not one with a dashed line drawn across
   it. The sheet carries 28px of stock below the perforation that is always
   clipped away — it is the slack the sheet bends into while the split travels,
   and it costs no layout because the margin takes it straight back. The pieces
   drop-shadow rather than box-shadow so the shadow follows the torn edge.
   Each sheet and stub drops the border along its own seam separately: that
   edge is not printed, it is torn, so it is declared where the border is. */
.tear-sheet {
  position: relative;
  margin-bottom: -28px;
}
.tear-stub {
  position: relative;
  margin-top: -5px;
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
}
/* Everything printed or torn along the seam. The overlay is a child of the
   piece it belongs to, so the clip takes the outer half of each stroke and
   leaves the inner half showing — which is how a torn edge catches the light,
   and how the last perforation before the split ends mid-dash. */
.tear-fringe {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  fill: none;
}
.tear-fibre {
  stroke: #FFFDF7;
  stroke-width: 1.6;
  stroke-linejoin: round;
}
.tear-perf {
  stroke: var(--perf, #ADA79A);
  stroke-width: 1;
  stroke-dasharray: 3.5 4.5;
}

/* The receipt sits slightly off-square, the way a slip of paper does. The
   wrapper carries nothing but that tilt and the depth the stub turns in. */
#receipt {
  pointer-events: auto;
  position: fixed;
  z-index: 10;
  left: 28px;
  bottom: 32px;
  width: 240px;
  transform: rotate(-0.6deg);
  perspective: 800px;
  /* Column, not blocks: the sheet and the stub both pull themselves up over
     the seam with negative margins, and adjoining block margins collapse to
     the more negative of the two instead of adding up. Flex items don't. */
  display: flex;
  flex-direction: column;
}
#receiptSheet {
  background: #FAF8F3;
  border: 1px solid #D8D4CB;
  border-bottom: 0;
  padding-bottom: 28px;
  filter: drop-shadow(0 12px 26px rgba(38, 38, 35, 0.15));
}
#receipt .line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
  align-items: baseline;
}
#receipt .line .k {
  font-size: 8px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #928F86;
  flex: none;
}
#receipt .line .v {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 11.5px;
  color: #262623;
  text-align: right;
  line-height: 1.4;
}
#stub {
  background: #FAF8F3;
  border: 1px solid #D8D4CB;
  border-top: 0;
  padding: 14px 14px 9px;
  text-align: center;
  font-size: 8px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #C05A38;
  filter: drop-shadow(0 9px 18px rgba(38, 38, 35, 0.14));
}
#stub:focus-visible {
  outline: 1px solid #C05A38;
  outline-offset: -3px;
}

/* The instruction sits on the field rather than on paper, so it needs its own
   ground -- over a dark glaze it was reading as noise. */
.hint {
  background: rgba(250, 248, 243, 0.92);
  border: 1px solid #D8D4CB;
  box-shadow: 0 8px 22px rgba(38, 38, 35, 0.10);
  padding: 9px 14px;
  font-size: 8px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #6E6C64;
}

/* Centred on the same axis as the sort and catalogue panels above it:
   those are right:28px by 254px wide, so their centre line is 155px in. */
#wheelWrap {
  pointer-events: auto;
  position: fixed;
  z-index: 11;
  right: 55px;
  bottom: 40px;
  width: 200px;
  height: 200px;
  transition: opacity .4s ease;
}
#wheelPointer {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 7px solid #C05A38;
  /* Base on the hub's edge (r=29), tip out towards the glyphs (r=53). */
  transform: translate(-50%, -50%) translateY(-32.5px);
  pointer-events: none;
}
#wheelWrap.faded {
  opacity: 0.12;
  pointer-events: none;
}
/* The palette reads as a thin band of glaze laid on a paper ring, so it sits
   with the dial rather than competing with it. */
#ringBase {
  position: absolute;
  /* Drawn from the outside in: inset pulls the outer edge to r=90 and the
     border says how much paper there is, so thinning the band keeps the 6px of
     field between it and the dial's 148px face rather than opening the two
     apart. 10px of paper, laid out from the inside: 2 paper, 3 arc, 1.5 gap,
     2 glaze, 1.5 paper. The two 1.5s are the same measure on purpose — the
     indicator sits off the glaze by exactly what the glaze sits off the edge.
     Hairlines in the same #D8D4CB the panels and the dial use. */
  inset: 10px;
  box-sizing: border-box;
  border: 10px solid #FAF8F3;
  border-radius: 50%;
  box-shadow: 0 8px 22px rgba(38, 38, 35, 0.10), 0 0 0 1px #D8D4CB, inset 0 0 0 1px #D8D4CB;
  touch-action: none;
}
#glazeRing {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  /* A 2px band at r86.5–88.5, leaving 1.5px of paper outside it before the
     edge at r90. Percentages are of the 100px half-box, not of the ring. */
  -webkit-mask: radial-gradient(circle farthest-side, transparent 86.1%, #000 86.5%, #000 88.5%, transparent 88.9%);
  mask: radial-gradient(circle farthest-side, transparent 86.1%, #000 86.5%, #000 88.5%, transparent 88.9%);
}
#ringArc {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
/* The range indicator was ink at 4.5px, which made the loudest mark on screen
   the scrollbar. It is drawn in the grey an unselected lattice glyph uses, so
   the two idle marks in the module weigh the same, at 3px so it still reads as
   the one moving part. It runs at r=83.5, inside the glaze and clear of it by
   the same 1.5px the glaze clears the paper's edge. The radius lives on the
   element; ui.js reads it rather than repeating it. */
#ringArcPath {
  fill: none;
  stroke: #BAB6AC;
  stroke-width: 3;
  stroke-linecap: round;
}
#wheelRing {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid #D8D4CB;
  background: radial-gradient(circle at 50% 38%, #FDFCF9, #F5F2EB);
  box-shadow: 0 12px 30px rgba(38, 38, 35, 0.18), inset 0 1px 4px rgba(38, 38, 35, 0.08);
}
#wheelRing.settling {
  transition: transform .3s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.glyph {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 30px;
  height: 30px;
  margin: -15px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Detail: the field stays visible but frosted, so an object reads against the
   colour it came from. */
#detail {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(243, 241, 236, 0.7);
  backdrop-filter: blur(34px) saturate(1.1);
  -webkit-backdrop-filter: blur(34px) saturate(1.1);
  overflow: auto;
  animation: fadein .22s ease;
}
#detail .plate {
  background: #FCFBF8;
  padding: 24px 24px 58px;
  transform: rotate(-1.4deg);
  box-shadow: 0 24px 60px rgba(38, 38, 35, 0.22);
  animation: cardin .4s ease;
}
/* The card and the coupon under it are one printed sheet until you take the
   coupon off, so they share a stack rather than each floating on their own. */
#detail .card-stack {
  width: 360px;
  perspective: 900px;
  animation: cardin2 .45s ease;
  display: flex;
  flex-direction: column;
}
#detail .card {
  --perf: #C6C0B4;
  background: #EFECE5;
  border: 1px solid #D8D4CB;
  border-bottom: 0;
  padding: 22px 24px 46px;
  position: relative;
  filter: drop-shadow(0 16px 38px rgba(38, 38, 35, 0.16));
}
#detail .coupon {
  display: block;
  background: #EFECE5;
  border: 1px solid #D8D4CB;
  border-top: 0;
  padding: 17px 24px 12px;
  text-align: center;
  font-size: 8px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  color: #262623;
  filter: drop-shadow(0 12px 26px rgba(38, 38, 35, 0.14));
}
#detail .coupon:hover { color: #C05A38; }
#detail .coupon:focus-visible {
  outline: 1px solid #C05A38;
  outline-offset: -3px;
}
#detail .card .field {
  padding: 7px 0;
  border-top: 1px solid #D8D4CB;
}
#detail .card .field .k {
  font-size: 8px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #928F86;
  margin-bottom: 3px;
}
#detail .card .field .v {
  font-family: 'Libre Baskerville', Georgia, serif;
  font-size: 12.5px;
  line-height: 1.5;
  color: #33322E;
}
#detail .attrs {
  flex-basis: 100%;
  display: flex;
  justify-content: center;
  gap: 52px;
  animation: cardin2 .5s ease;
}

/* Keycaps, because these actions are all reachable from the keyboard and the
   overlay should say so rather than imply it with a bare glyph. */
/* Flat outlines rather than keycaps: no ground, no weighted bottom edge, just
   the rule around the label. The overlay is already frosted paper, so a filled
   button was a second surface laid on a surface. */
.key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 34px;
  height: 26px;
  padding: 0 9px;
  background: transparent;
  border: 1px solid #BAB6AC;
  border-radius: 4px;
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #262623;
  transition: border-color .15s ease, color .15s ease;
}
/* Without a ground to press, the outline is what has to answer the pointer. */
.key:hover {
  border-color: #6E6C64;
  color: #262623;
}
.key--nav {
  min-width: 42px;
  height: 38px;
  font-size: 16px;
  letter-spacing: 0;
  color: #6E6C64;
}
.key--mini {
  min-width: 22px;
  height: 19px;
  padding: 0 5px;
  font-size: 8px;
  border-color: #C9C5BB;
}
#detailHint {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 6px;
  /* A hint should sit under everything else in the room: no card, no shadow,
     just the words on the frost. */
  padding: 7px 12px;
  background: rgba(250, 248, 243, 0.5);
  border: 1px solid rgba(216, 212, 203, 0.55);
  font-size: 8px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #928F86;
  white-space: nowrap;
}
/* The mini caps ride inside the hint, so they lighten with it. */
#detailHint .key--mini { color: #6E6C64; }
#detailHint .key--mini:hover { border-color: #C9C5BB; }

#boot {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #F3F1EC;
  text-align: center;
  transition: opacity .4s ease;
}
#boot.gone {
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  #detail, #detail .plate, #detail .card-stack, #detail .attrs { animation: none }
  #wheelRing.settling, #catPanel { transition: none }
  /* tear.js checks the same query and leaves the paper alone: no drag, no
     swing, no fall — the stub is simply a button that does the thing. */
}
