/* ================================================================
   Cascade layers

   Everything that sets a DEFAULT for an element or a region goes in
   @layer base. Everything else — components like .ig, .btn, .shop,
   .key__heading — stays unlayered.

   Unlayered rules beat every layered rule no matter how specific the
   layered one is, so `.band p` can no longer out-specify `.cat__count`,
   and `h3.tape` can no longer out-specify `.key__heading`. A component
   never has to be written defensively to win against a default.

   Rule of thumb when adding CSS:
     styling an element or a whole region?  ->  @layer base { ... }
     styling one named thing?               ->  leave it unlayered
   ================================================================ */
@layer base;

:root{
  --paper:#f9f7f1;
  --ink:#111;
  --rule:2px solid var(--ink);
  --shadow:7px 7px 0 rgba(17,17,17,.9);
  --pad:52px;
}
@layer base{
  *,*::before,*::after{box-sizing:border-box}
  html{scroll-behavior:smooth}
  body{
    margin:0;background:var(--paper);color:var(--ink);
    font-family:'IBM Plex Sans',system-ui,-apple-system,sans-serif;
    -webkit-font-smoothing:antialiased;
  }
  img{max-width:100%}
  /* Only 400, 500 and 600 are loaded. Left at the default bold (700) the
     browser would synthesise a heavier face instead of using the real one. */
  strong,b{font-weight:600}
  a{color:var(--ink)}
  a:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
}

.page{max-width:1180px;margin:0 auto;background:var(--paper);border-left:var(--rule);border-right:var(--rule);overflow:hidden}

/* ---- accessibility utilities ---- */
/* Off-screen until focused, then a taped label in the top-left. Fixed, and
   above the sticky header's z-index:20. */
.skip{
  position:fixed;top:-120px;left:var(--pad);z-index:100;
  font-family:'Special Elite',monospace;font-size:15px;text-decoration:none;
  background:var(--ink);color:var(--paper);border:var(--rule);padding:10px 18px;
}
.skip:focus{top:12px}
/* Available to screen readers, removed from the visual layout. */
.sr-only{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}
/* Buttons and fields get the same offset ring as links. Without the offset an
   ink ring on an ink-filled button is invisible. */
@layer base{
  button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{
    outline:2px solid var(--ink);outline-offset:3px;
  }
}

/* ---- typewriter box treatment ---- */
.tape{
  font-family:'Special Elite',monospace;font-weight:400;
  color:var(--paper);background:var(--ink);display:inline-block;
}
.tape--invert{color:var(--ink);background:var(--paper)}

/* ---- header ---- */
.masthead{
  display:flex;align-items:center;justify-content:space-between;gap:24px;
  padding:18px 32px;border-bottom:var(--rule);
  position:sticky;top:0;background:var(--paper);z-index:20;
}
.wordmark{font-family:'Special Elite',monospace;font-size:19px;text-decoration:none;letter-spacing:.01em}
.nav{font-size:13.5px;font-weight:500;text-transform:uppercase;letter-spacing:.08em}
.nav ul{display:flex;align-items:center;gap:22px;list-style:none;margin:0;padding:0}
/* :not(.ig) stays: layering settles conflicts over the same property, but the
   icon button never declares padding or border-bottom, so it would still
   inherit them from a region default. */
@layer base{
  .nav a:not(.ig){text-decoration:none;padding:4px 0;border-bottom:2px solid transparent}
  .nav a:not(.ig):hover{border-bottom-color:var(--ink)}
}
/* Icon button: 38x38 with an inset ring rather than a border — a 2px border on
   a box that lands on a fractional pixel drops an edge at some zoom levels. */
.ig{
  display:flex;align-items:center;justify-content:center;flex:none;
  width:38px;height:38px;color:var(--ink);
  box-shadow:inset 0 0 0 2px var(--ink);
}
.ig:hover{background:var(--ink);color:var(--paper)}

/* ---- hero ---- */
.hero{position:relative;border-bottom:var(--rule)}
/* Tuned for hero-truck.jpg: keeps the DONUTS sign legible above the donut.
   Only the vertical value does anything — the source is portrait, so cover
   fills the width exactly and there is nothing to slide horizontally.
   hero-donut.jpg, the previous hero, wanted `center 40%`. */
.hero__img{display:block;width:100%;height:600px;object-fit:cover;object-position:center 30%}
.hero__title{
  position:absolute;top:150px;left:var(--pad);margin:0;
  font-size:74px;line-height:1;padding:16px 26px;
  transform:rotate(-1.4deg);letter-spacing:.005em;
  scroll-margin-top:90px;
}
/* Focused via the skip link. Paper outline — an ink one would sit on the ink
   box and disappear. */
.hero__title:focus-visible{outline:2px solid var(--paper);outline-offset:3px}
.hero__sub{
  position:absolute;top:264px;left:210px;margin:0;
  font-family:'Special Elite',monospace;font-size:28px;
  color:var(--paper);background:var(--ink);padding:10px 18px;transform:rotate(1.2deg);
}
.hero__card{
  position:absolute;bottom:38px;left:var(--pad);width:560px;
  background:var(--paper);border:var(--rule);padding:22px 24px;
  transform:rotate(-.5deg);box-shadow:var(--shadow);
}
.hero__card p{margin:0;font-size:16.5px;line-height:1.6;text-wrap:pretty}

/* ---- sections ---- */
.band{padding:60px var(--pad);border-bottom:var(--rule)}
.band--intro{padding-top:56px;display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:start}
.band--bakeries{display:grid;grid-template-columns:1.35fr 1fr;gap:48px;align-items:start}
/* Region defaults: any component class overrides these without a fight. */
@layer base{
  .band p{font-size:17px;line-height:1.65;text-wrap:pretty}
  h2.tape{margin:0 0 26px;font-size:34px;line-height:1.1;padding:11px 18px}
  h3.tape{margin:0 0 16px;font-size:19px;line-height:1.2;padding:8px 14px}
}
.band--intro p{margin:0}
.tilt-l{transform:rotate(-1deg)}
.tilt-r{transform:rotate(.8deg)}

.figure{margin:0;transform:rotate(1.8deg)}
/* cruller-hand.jpg is a 3:4 portrait. Square keeps the cruller and the whole
   hand while trimming the bakery cases at the top; the full portrait would run
   ~600px against a 300px text column and unbalance the row. 60% favours the
   lower half, where the hand is. */
.figure img{
  display:block;width:100%;height:auto;aspect-ratio:1/1;
  object-fit:cover;object-position:center 60%;
  border:var(--rule);box-shadow:var(--shadow);
}
.figure figcaption{
  margin-top:12px;font-family:'Special Elite',monospace;font-size:12.5px;
  color:var(--paper);background:var(--ink);border:1px solid var(--ink);
  display:inline-block;padding:4px 9px;transform:rotate(-2.2deg);
}

/* ---- maps ---- */
#maps{scroll-margin-top:78px}
.maps__grid{display:grid;grid-template-columns:1fr 1.1fr;gap:44px;align-items:start}
.maps__copy p:first-child{margin:0 0 18px}
.maps__copy p:last-of-type{margin:0 0 26px}
.actions{display:flex;flex-wrap:wrap;gap:12px}
.btn{
  font-family:'Special Elite',monospace;font-size:16px;text-decoration:none;
  border:var(--rule);padding:12px 20px;background:var(--paper);color:var(--ink);
}
.btn:hover{background:var(--ink);color:var(--paper)}
.btn--solid{background:var(--ink);color:var(--paper)}
.btn--solid:hover{background:var(--paper);color:var(--ink)}

.mapcard{border:var(--rule);background:var(--paper);padding:14px;transform:rotate(-.7deg);box-shadow:var(--shadow)}
.mapcard__frame{
  height:280px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  background:repeating-linear-gradient(45deg,rgba(17,17,17,.05) 0 8px,transparent 8px 16px);
  border:1px dashed rgba(17,17,17,.4);text-align:center;padding:12px;
}
.mapcard__frame span:first-child{font-family:'Special Elite',monospace;font-size:15px}
.mapcard__frame span:last-child{font-size:12px;color:#555;letter-spacing:.04em}
.mapcard iframe{display:block;width:100%;height:280px;border:0}
/* Taller on the map page, where the embed is the point of the section. */
.mapcard--tall iframe{height:420px}
.chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.chip{font-size:11.5px;font-weight:500;text-transform:uppercase;letter-spacing:.07em;border:var(--rule);padding:4px 9px}
.chip--on{background:var(--ink);color:var(--paper)}

/* ---- footer ---- */
.foot{
  background:var(--ink);color:var(--paper);padding:44px var(--pad);
  display:grid;grid-template-columns:1fr 1fr;gap:40px;scroll-margin-top:78px;
}
.foot h2{margin:0 0 16px;font-size:19px;letter-spacing:.06em;padding:8px 14px}
.foot ul{display:flex;flex-direction:column;gap:9px;font-size:15px;list-style:none;margin:0;padding:0}
@layer base{
  .foot a:not(.ig){color:var(--paper);text-decoration:none;padding:2px 0;border-bottom:2px solid transparent;width:fit-content}
  .foot a:not(.ig):hover{border-bottom-color:var(--paper)}
  .foot a:focus-visible{outline-color:var(--paper)}
}
.foot .email{display:block;width:fit-content;margin:16px 0;font-size:15px}
.foot .ig{box-shadow:inset 0 0 0 2px var(--paper);color:var(--paper);display:inline-flex}
.foot .ig:hover{background:var(--paper);color:var(--ink)}

/* ---- mobile ---- */
@media (max-width:900px){
  :root{--pad:24px}
  .page{border-left:0;border-right:0}
  .masthead{padding:14px 20px;flex-wrap:wrap;gap:12px}
  .nav ul{gap:16px}
  .nav{font-size:12px}
  .hero__img{height:340px}
  .hero__title{position:static;font-size:34px;margin:-1px 0 0;padding:10px 14px;display:block;width:fit-content}
  .hero__sub{position:static;font-size:17px;margin:10px 0 0 24px;display:inline-block;padding:6px 11px}
  .hero{padding-bottom:24px}
  .hero__title,.hero__sub{margin-left:var(--pad)}
  .hero__card{position:static;width:auto;margin:22px var(--pad) 0;box-shadow:5px 5px 0 rgba(17,17,17,.9)}
  .band--intro,.band--bakeries,.maps__grid,.foot{grid-template-columns:1fr;gap:28px}
  .band{padding:36px var(--pad)}
  /* Single column here, so the figure spans the full width. Square would be as
     tall as the screen is wide; 4:3 with a cap keeps it in proportion. */
  .figure img{aspect-ratio:4/3;max-height:400px}
  .figure{transform:rotate(1deg)}
  h2.tape{font-size:26px}
  .mapcard{transform:rotate(-.5deg)}
}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

/* ================================================================
   Raleigh Donut Map page
   ================================================================ */
.band--pagehead{padding-bottom:0;border-bottom:0}
.pagetitle{
  margin:0;font-size:52px;line-height:1.05;padding:14px 24px;
  transform:rotate(-1.2deg);display:inline-block;scroll-margin-top:90px;
}
.pagetitle:focus-visible{outline:2px solid var(--paper);outline-offset:3px}

.aboutcard{
  background:var(--paper);border:var(--rule);padding:22px 24px;
  box-shadow:var(--shadow);transform:rotate(-.4deg);max-width:760px;
}
.aboutcard p{margin:0;font-size:16.5px;line-height:1.6;text-wrap:pretty}
/* Links inside running text stay underlined. Nothing in this palette changes
   colour on hover, so the underline is the only thing marking them as links —
   the hover-only border used on standalone links would leave them invisible
   mid-sentence. */
.aboutcard a,.prose a,.postbody a,.mapside__blurb a,.contact__intro a{
  text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:3px;
}

/* Body copy is capped for line length — full band width is far too wide to read. */
.prose{max-width:680px}
.prose p{margin:0 0 20px}
.prose p:last-child{margin-bottom:0}

.about__lists{display:grid;grid-template-columns:1fr 2fr;gap:44px;margin-top:40px}
/* h3.tape sizing lives in @layer base, with the other heading defaults. */
.plainlist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;font-size:15px}
.plainlist--wrap{flex-direction:row;flex-wrap:wrap;gap:8px 18px}

/* ---- map embed ---- */
/* Off-screen until focused, then it takes its place above the map. */
.btn--skipmap{
  position:absolute;width:1px;height:1px;padding:0;margin:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;
}
.btn--skipmap:focus{
  position:static;width:auto;height:auto;clip-path:none;overflow:visible;
  display:inline-block;margin:0 0 20px;padding:12px 20px;border:var(--rule);
  font-size:15px;
}
.maplayout{display:grid;grid-template-columns:1.6fr 1fr;gap:36px;align-items:start}
.mapcard__frame--tall{height:420px}
.mapside{display:flex;flex-direction:column;gap:18px;align-items:flex-start}
.mapside__blurb{border:var(--rule);background:var(--paper);padding:18px 20px;transform:rotate(.5deg)}
.mapside__blurb p{margin:0;font-size:15.5px;line-height:1.6}

/* The right column of .maplayout is taller than the map card, so this margin
   is what holds the heading off the "Open in Google Maps" button. */
.key__heading{margin:48px 0 16px}
.key{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:14px 30px}
.key__item{display:flex;align-items:center;gap:10px}
/* The pins are the real Google My Maps markers, so they keep their own colors. */
.key__item img{width:auto;height:42px;display:block}
.key__item span{font-size:13.5px;font-weight:500;text-transform:uppercase;letter-spacing:.07em}

/* ---- filters ---- */
.filters{border:var(--rule);background:var(--paper);padding:22px 24px;margin:0 0 28px;box-shadow:var(--shadow)}
.filters__search{display:flex;flex-direction:column;gap:8px}
.filters__search label{font-size:13.5px;font-weight:500;text-transform:uppercase;letter-spacing:.08em}
.filters__searchrow{display:flex;gap:10px;flex-wrap:wrap}
.filters__searchrow input{
  flex:1 1 240px;font-family:inherit;font-size:16px;padding:11px 14px;
  border:var(--rule);background:var(--paper);color:var(--ink);border-radius:0;
}
.filters__searchrow input:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
/* #555 on paper is 6.9:1. The browser default placeholder grey is about 4.2:1
   and fails AA. */
.filters__searchrow input::placeholder{color:#555;opacity:1}
/* The native clear affordance on type=search is not reachable by keyboard and
   has no accessible name, so it is hidden — "Clear search" replaces it. */
.filters__searchrow input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none;display:none}
.filters__actions{margin:22px 0 0;padding:18px 0 0;border-top:var(--rule)}
.filters__group{border:0;margin:22px 0 0;padding:18px 0 0;border-top:var(--rule)}
.filters__group legend{
  font-size:13.5px;font-weight:500;text-transform:uppercase;letter-spacing:.08em;
  padding:0;margin:0 0 12px;
}
.tagboxes{display:flex;flex-wrap:wrap;gap:10px 22px}
.tagbox{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer}
/* Custom box — the native control's outline is a system grey that cannot be
   restyled, and this system has no grey. */
.tagbox input{
  appearance:none;-webkit-appearance:none;margin:0;flex:none;
  width:18px;height:18px;border:2px solid var(--ink);background:var(--paper);
  display:grid;place-content:center;cursor:pointer;
}
.tagbox input:checked{background:var(--ink)}
.tagbox input:checked::after{
  content:"";width:5px;height:10px;margin-top:-2px;
  border:solid var(--paper);border-width:0 2px 2px 0;transform:rotate(45deg);
}
.tagbox__n{color:#555;font-size:12.5px}

/* Paragraphs inside .band take their size and line-height from `.band p`,
   which out-specifies a single class. Only override with a selector that
   beats it — see .aboutcard p. */
.results{
  font-family:'Special Elite',monospace;margin:0 0 8px;
  background:var(--ink);color:var(--paper);display:inline-block;padding:7px 14px;
  transform:rotate(-.6deg);
}
.noresults{margin:12px 0 0;max-width:560px}

/* ---- the list ---- */
.cat{margin:44px 0 0}
.cat[hidden]{display:none}
.cat__count{
  font-weight:500;text-transform:uppercase;letter-spacing:.07em;
  color:#555;margin:0 0 20px;
}
.shops{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:24px}
.shop{border:var(--rule);background:var(--paper);padding:20px 22px}
.shop[hidden]{display:none}
.shop__name{font-family:'Special Elite',monospace;font-weight:400;font-size:21px;margin:0 0 8px;line-height:1.2}
.shop__address{margin:0 0 6px}
/* Special Elite, matching the shop name above it. */
.shop__label{
  font-family:'Special Elite',monospace;font-weight:400;font-size:17px;
  color:var(--ink);margin:0;
}
.shop__site{font-size:14.5px;display:inline-block;width:fit-content;padding:2px 0;border-bottom:2px solid transparent}
a.shop__site:hover{border-bottom-color:var(--ink)}
.shop__site--none{color:#555;border-bottom:0}
/* Label sits on the same line as the chips and wraps with them. */
.shop__tagrow{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:14px 0 0}
.shop__tags{list-style:none;display:flex;flex-wrap:wrap;gap:7px;margin:0;padding:0}
.shop__desc{margin:14px 0 0}

@media (max-width:900px){
  .pagetitle{font-size:32px}
  .about__lists,.maplayout,.shops{grid-template-columns:1fr;gap:24px}
  .mapcard--tall iframe{height:300px}
  .filters{padding:18px}
}

/* ================================================================
   Blog
   ================================================================ */
.blog__intro{max-width:640px;margin:0 0 40px}

.posts{list-style:none;margin:0;padding:0}
.post{margin:0 0 36px}
.post__title{
  font-family:'Special Elite',monospace;font-weight:400;font-size:26px;
  margin:0 0 6px;line-height:1.25;
}
.post__title a{text-decoration:none;border-bottom:2px solid transparent}
.post__title a:hover{border-bottom-color:var(--ink)}
.post__date{
  font-size:13.5px;font-weight:500;text-transform:uppercase;letter-spacing:.07em;
  color:#555;margin:0;
}
/* The rule under each post, with the doughnut sitting on its left end. */
.post__rule{display:flex;align-items:center;gap:12px;margin-top:16px}
.post__rule span{flex:1;height:2px;background:var(--ink)}
.donut{flex:none;color:var(--ink)}

.postbody{max-width:680px;margin:28px 0 0}
.postbody p{margin:0 0 20px}
.postbody p:last-child{margin-bottom:0}
.postback{margin:40px 0 0}
.postback a{text-decoration:none;border-bottom:2px solid transparent;padding:2px 0}
.postback a:hover{border-bottom-color:var(--ink)}

/* ================================================================
   Contact
   ================================================================ */
.contact__intro{max-width:640px;margin:0 0 40px}
.contact__intro p{margin:0 0 14px}
.contact__intro p:last-child{margin-bottom:0}

.contactform{max-width:620px}
.field{display:flex;flex-direction:column;gap:8px;margin:0 0 22px}
.field label{font-size:13.5px;font-weight:500;text-transform:uppercase;letter-spacing:.08em}
.field input,.field textarea{
  font-family:inherit;font-size:16px;padding:11px 14px;border-radius:0;
  border:var(--rule);background:var(--paper);color:var(--ink);width:100%;
}
.field textarea{resize:vertical;min-height:160px;line-height:1.6}
.contactform button{cursor:pointer}

/* No red in this palette, so an error cannot be signalled by colour. It is an
   inverted label — a shape change, legible to everyone — and the field it
   belongs to doubles its edge. */
.field__error{
  font-family:'Special Elite',monospace;font-size:14px;
  background:var(--ink);color:var(--paper);
  display:inline-block;width:fit-content;padding:6px 11px;margin:2px 0 0;
}
.field__error[hidden]{display:none}
.field :is(input,textarea)[aria-invalid="true"]{
  box-shadow:inset 0 0 0 2px var(--ink);
}

/* Shown in place of the form after a successful send. */
.formnote{
  border:var(--rule);background:var(--paper);box-shadow:var(--shadow);
  padding:22px 24px;max-width:620px;transform:rotate(-.4deg);
}
.formnote p{
  font-family:'Special Elite',monospace;font-size:19px;line-height:1.4;margin:0;
}
.formnote:focus-visible{outline:2px solid var(--ink);outline-offset:5px}
.contactform button[disabled]{opacity:.65;cursor:default}
#form-error{margin-top:14px}
/* Honeypot: a real field, hidden from people, that bots tend to fill in.
   Netlify discards any submission that arrives with it filled. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

@media (max-width:900px){
  .post__title{font-size:21px}
}

/* Photo at the top of a blog post. Capped to the body's measure so it does not
   outrun the text it belongs to. */
.postimage{margin:28px 0 0;max-width:680px}
/* Capped by height as well as width, so a portrait photo does not run to ~900px
   and swallow the screen. Nothing is cropped — the image scales down whole and
   the figure shrinks with it. A landscape photo is unaffected; it hits the
   width limit first. */
.postimage img{
  display:block;width:auto;max-width:100%;height:auto;max-height:620px;
  border:var(--rule);box-shadow:var(--shadow);transform:rotate(-.6deg);
}

/* Bulleted list inside a post. Square markers — this system has no rounded
   corners anywhere else either. */
.postlist{margin:0 0 20px;padding-left:1.4em;max-width:680px;list-style:square}
.postlist li{margin:0 0 10px;padding-left:.2em}
.postlist li:last-child{margin-bottom:0}
.postlist li::marker{color:var(--ink)}

/* Subheading inside a post. Needs air above it — the taped heading default
   carries a bottom margin only, which is fine at the top of a section but too
   tight when paragraphs run into it. Sized down from the 34px section
   headings, which overpower a 680px column of body copy. */
.postheading{margin:44px 0 20px;font-size:25px;max-width:680px}
