@charset "utf-8";

/* ===========================================================================
   dol.css — 円卓の冒険団 (Adventurers of the Round Table)
   ---------------------------------------------------------------------------
   One design system for all 54 pages under dol/. It replaces the 2021
   Bootstrap template, the seven vendor stylesheets that came with it, and the
   inline <style> block that each of the 50 diary pages carried.

   THE IDEA — "Soundings".
   The site already owned the palette: img/hero-bg.jpg is a flat turquoise
   lagoon under a bleached warm horizon with a hard drop-off into deep blue.
   Every colour below is sampled off that ladder, so there is no grey and no
   black anywhere in this file — the neutrals are all desaturated sea. The
   site is a logbook the founder opened in 2005 and never closed, so the date
   outranks the title on all 198 entries, the 【宿泊地】 sign-off is set as a
   real log field, and 2005 → 2007 steps down the ladder from the shallows
   into the dark. The one warm thing on a cool page is a brass hairline
   streaming off the right of every section heading: that is the wind.

   Sibling sections of this site (hl/, bc/) are near-black. This one is the
   light one on purpose, and it does not offer an auto dark variant — light is
   its identity, and three dark navy sections would be the stranger, not the
   sibling.

   Layout is mobile-first. Breakpoints: 600 / 700 / 900 / 1120px.
   =========================================================================== */

/* ------------------------------------------------------------------ tokens */

:root {
  color-scheme: light;

  /* surfaces — warm paper ground, sea values above it */
  --sail:    #fdfcf8;   /* page ground, card fill, frozen-column fill      */
  --shoal:   #e8f4f2;   /* crumb bar, zebra rows, panels, screenshot mats  */
  --swell:   #c9e6e2;   /* row hover, nav hover pill                       */
  /* the hero band is the only warm pale in the set; it is written literally
     in .hero__band because that rule also needs an alpha and an @supports
     twin, and a token that only ever appears inside rgb() indirection reads
     worse than the value */
  --sky:     #a9d4ea;   /* ::selection, and the colour under the hero photo */
  --trench:  #041a2b;   /* footer ground, lightbox backdrop                */

  /* ink */
  --abyss:    #06263d;  /* body text and headings. Never #000.             */
  --ink-soft: #3f5f72;  /* captions, dates, breadcrumbs, table meta        */
  --foam:     #8fb4c2;  /* secondary text, on --trench only                */

  /* accents */
  --link: #0a6273;      /* links. Deliberately darker than --drop: long
                           Japanese link runs stay comfortable to read.    */
  --drop: #0e7c8c;      /* the reef edge. Eyebrows, focus ring, reply bar. */
  --deep: #0b5372;      /* solid fills that carry --sail text              */
  --reef: #6fcbc4;      /* decorative mid-water. Never text.               */

  /* brass — split into two tokens so the rule cannot be broken by accident.
     --brass is 2.96:1 on --sail, so it is fill, ring and hairline ONLY.
     A warm thing that must carry text uses --brass-ink (5.76:1). */
  --brass:     #c08a2e;
  --brass-ink: #8a5a12;

  /* lines — --lagoon is 1.31:1 and decorative: it is never the only thing
     marking a boundary a reader has to perceive. Structure uses --rule-deep
     (3.35:1). */
  --lagoon:    #bee6e0;
  --rule-deep: #6e8fa0;

  /* year as depth: set once per page by a class on <html>. Colour is always
     redundant — every stamp also spells the year out. */
  --yr-2005: #0e7c8c;
  --yr-2006: #0b5372;
  --yr-2007: #06263d;
  --yr: var(--yr-2006);

  /* the bathymetric strip. HARD stops, never a smooth ramp — a soft
     two-stop blue ramp is the stock-template tell. */
  --waterline: linear-gradient(90deg,
      var(--lagoon) 0 22%, var(--reef) 22% 34%, var(--drop) 34% 35%,
      var(--deep) 35% 62%, var(--abyss) 62%);

  /* shadows are all tinted with sea. One neutral shadow and the page stops
     sitting under a sky and starts sitting under an office ceiling. */
  --shadow-1: 0 1px 2px rgb(6 38 61 / .05);
  --shadow-2: 0 10px 24px -14px rgb(11 83 114 / .22);

  /* type */
  --f-body: "Hiragino Sans", "Hiragino Kaku Gothic ProN", "BIZ UDPGothic",
            "Noto Sans JP", "Yu Gothic Medium", "游ゴシック Medium", YuGothic,
            "Yu Gothic", Meiryo, system-ui, sans-serif;
  /* "Yu Mincho Demibold" is named explicitly: Yu Mincho has no true bold and
     font-synthesis is off, so this is the only way Windows gets a usable
     display weight. If a machine has no Japanese serif at all the stack falls
     back to gothic and nothing breaks — hierarchy here is carried by size,
     colour and the brass rule, not by the face. */
  --f-display: "Hiragino Mincho ProN", "Yu Mincho Demibold", "游明朝 Demibold",
               "Yu Mincho", YuMincho, "游明朝", "BIZ UDPMincho", "Noto Serif JP",
               "Source Han Serif JP", "MS PMincho", "Iowan Old Style",
               "Palatino Linotype", Georgia, serif;
  /* BIZ UDGothic sits ahead of the generic keyword so a 年月日 date never
     falls back to a face with no kanji coverage. */
  --f-mono: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono",
            Menlo, Consolas, "BIZ UDGothic", monospace;

  --fs-hero:  clamp(1.75rem, 1.1rem + 3.2vw, 3.25rem);
  --fs-h1:    clamp(1.5rem, 1.15rem + 1.6vw, 2.5rem);
  --fs-h2:    clamp(1.25rem, 1.05rem + .9vw, 1.75rem);
  --fs-h3:    1.25rem;
  --fs-stamp: clamp(1.0625rem, 1rem + .5vw, 1.3125rem);
  --fs-body:  clamp(1rem, .97rem + .15vw, 1.0625rem);  /* 16px is the floor */
  --fs-sm:    .875rem;
  --fs-xs:    .8125rem;
  --fs-label: .75rem;

  --lh-jp:   1.9;    /* diary prose      */
  --lh-body: 1.85;   /* everything else  */
  --lh-head: 1.5;    /* kanji fill the em box; Latin's 1.15 suffocates them */

  /* space, geometry, measure */
  --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;   --sp-7: 3rem;    --sp-8: 4rem;
  --sp-sec: clamp(2.5rem, 6vw, 4.5rem);

  --radius: 10px;        /* cards and panels. 16px+ pills are the SaaS tell */
  --radius-sm: 6px;
  --radius-pill: 999px;
  /* --head-h is the bar's own min-height. What anchors and the sticky table
     head have to clear is the whole masthead, which is 3px taller: the bar,
     the 2px waterline strip drawn by .site-head::after, and the 1px border. */
  --head-h: 56px;
  --head-total: 59px;

  --wrap: min(100% - 2.5rem, 1120px);
  --measure: 40em;       /* about 40 full-width Japanese characters */
}

html.y2005 { --yr: var(--yr-2005); }
html.y2006 { --yr: var(--yr-2006); }
html.y2007 { --yr: var(--yr-2007); }

/* ------------------------------------------------- cross-document nav */

/* Same-origin navigations cross-fade rather than flash. Browsers without
   support just navigate; the reduced-motion block below turns it off for
   anyone who has asked for that. */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .2s;
  animation-timing-function: cubic-bezier(.4, 0, .2, 1);
}

/* --------------------------------------------------------------- reset-ish */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* anchor jumps must not land under the sticky masthead */
  scroll-padding-block-start: calc(var(--head-total) + 1rem);
  font-synthesis: none;   /* stops Windows faux-bolding Mincho into mush */
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--f-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: .02em;          /* Japanese wants a hair of tracking */
  color: var(--abyss);
  background: var(--sail);
  line-break: strict;             /* keep kinsoku */
  word-break: normal;             /* never break-all: it mangles Japanese */
  overflow-wrap: break-word;
  overflow-x: clip;               /* `clip`, not `hidden`: sticky keeps working */
  text-autospace: normal;
}

img, video, svg { max-width: 100%; height: auto; border: 0; display: block; }

a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { color: var(--drop); }
a:visited { color: #6a5aa0; }

:focus-visible {
  outline: 3px solid var(--drop);
  outline-offset: 2px;
  /* deliberately no border-radius here: outline already follows the
     element's own radius, and setting one would square a 999px chip the
     instant it takes focus */
}

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

::selection { background: var(--sky); color: var(--abyss); }

/* Mincho only at 1.25rem and up — below that Yu Mincho renders as hairlines
   on Windows. Never bold: 500 is the ceiling. */
h1, h2, h3, .brand__txt b {
  font-family: var(--f-display);
  font-weight: 500;
  line-height: var(--lh-head);
  letter-spacing: .04em;
  font-feature-settings: "palt" 1;   /* display only — palt on body text
                                        destroys the vertical character grid */
  color: var(--abyss);
  margin: 0;
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

.prose { line-height: var(--lh-jp); max-width: var(--measure); }
.prose a, .linkcard a { overflow-wrap: anywhere; }  /* 2005-era bare URLs */

.wrap { width: var(--wrap); margin-inline: auto; }

.skip { position: absolute; inset-inline-start: -9999px; z-index: 200; }
.skip:focus {
  inset: 1rem auto auto 1rem;
  background: var(--deep);
  color: var(--sail);
  padding: .6rem 1rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
}

/* Latin-and-numeral slots may be tracked; Japanese may not be tracked past
   .04em, and not at all below 1.25rem. The guard is :not([lang="en"]) and
   NOT :lang(ja) — the pages carry <html lang="ja">, so a :lang(ja) rule would
   match every element on the site and strip the tracking it is protecting. */
.eyebrow, .chip, .card .k, .site-foot h2, .counter__k, .stamp {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .12em;
}
.eyebrow:not([lang="en"]), .chip:not([lang="en"]),
.card .t:not([lang="en"]) { letter-spacing: .02em; }

/* ------------------------------------------------------ the waterline strip */

/* Rationed to three placements — under the masthead, closing the hero, above
   the footer. Put it under every section on 54 pages and it is wallpaper. */
.site-head::after,
.hero::after,
.site-foot::before {
  content: "";
  display: block;
  height: 2px;
  background: var(--waterline);
}

/* --------------------------------------------------------------- masthead */

.site-head {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgb(253 252 248 / .88);
  backdrop-filter: blur(10px) saturate(1.15);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  border-bottom: 1px solid var(--lagoon);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-head { background: var(--sail); }
}

.site-head__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: var(--head-h);
  /* the nav is a flex child; below 900px it has to break to its own
     full-width row or the open drawer sits beside the brand as a column */
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: .55rem;
  text-decoration: none;
  color: var(--abyss);
  flex: 0 0 auto;
  padding-block: .4rem;
}
.brand:visited { color: var(--abyss); }

/* The 40x25 ship is white on transparency and would vanish on cream. The
   badge makes it legible without masking, filtering or upscaling it. */
.brand__badge {
  display: grid;
  place-items: center;
  padding: 6px 8px;
  background: var(--deep);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
}
.brand__badge img { width: 40px; height: 25px; }

.brand__txt b { display: block; font-size: 1.06rem; line-height: 1.15; }
.brand__txt i {
  display: block;
  font-family: var(--f-mono);
  font-style: normal;
  font-size: .6rem;
  letter-spacing: .28em;
  color: var(--drop);
  line-height: 1.5;
}
.brand:hover b { color: var(--deep); }

.nav-toggle {
  display: none;
  margin-inline-start: auto;
  align-items: center;
  gap: .5rem;
  font-family: var(--f-mono);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--deep);
  background: var(--shoal);
  border: 1px solid var(--lagoon);
  border-radius: var(--radius-pill);
  padding: .55rem .9rem;
  min-height: 44px;
  cursor: pointer;
}
.nav-toggle:hover { background: var(--swell); }
.nav-toggle .bars { display: grid; gap: 3px; }
.nav-toggle .bars span { display: block; width: 16px; height: 2px; background: currentColor; }
.nav-toggle[aria-expanded="true"] { background: var(--deep); color: var(--sail); border-color: var(--deep); }

.site-nav ul { list-style: none; margin: 0; padding: 0; }
.site-nav a {
  display: block;
  font-family: var(--f-mono);
  font-size: .8rem;
  letter-spacing: .1em;
  color: var(--abyss);
  text-decoration: none;
  padding: .8rem .2rem;
  border-bottom: 1px solid var(--lagoon);
}
.site-nav a:visited { color: var(--abyss); }
.site-nav a:hover { color: var(--deep); }
/* aria-current marks the page you are on; .is-section marks the section it
   belongs to (a member's diary is under Members but is not the roster). They
   look the same on purpose — only one of them is a claim about the page. */
.site-nav a[aria-current="page"],
.site-nav a.is-section { color: var(--deep); box-shadow: inset 0 -2px 0 var(--brass); }
.site-nav .is-ext::after { content: " ↗"; color: var(--drop); font-size: .85em; }

/* The drawer only exists when scripting does. With JS off the list simply
   stays visible and the toggle stays hidden, so every page is complete.
   It does mean the masthead is then ~300px tall below 900px, which is far too
   much to keep pinned to the top of a phone screen — and it would swallow
   every anchor target, since scroll-padding is sized for the 59px bar. So
   without scripting the masthead simply scrolls away like normal content. */
html:not(.js) .site-head { position: static; }
.js .site-nav { display: none; flex: 0 0 100%; padding-block: 0 var(--sp-3); }
.js .site-nav.is-open { display: block; }
.js .nav-toggle { display: flex; }

@media (min-width: 900px) {
  .site-head__bar { flex-wrap: nowrap; }
  .js .nav-toggle { display: none; }
  .js .site-nav, .site-nav { display: block; flex: 0 1 auto; margin-inline-start: auto; padding: 0; }
  .site-nav ul { display: flex; align-items: center; gap: .15rem; }
  .site-nav a {
    padding: .5rem .7rem;
    border: 0;
    border-radius: var(--radius-pill);
    white-space: nowrap;
  }
  .site-nav a:hover { background: var(--swell); }
  .site-nav a[aria-current="page"],
  .site-nav a.is-section { box-shadow: inset 0 -2px 0 var(--brass); border-radius: var(--radius-sm); }
}

/* ------------------------------------------------------------ breadcrumbs */

.crumbs {
  background: var(--shoal);
  border-bottom: 1px solid var(--lagoon);
}
.crumbs ol {
  list-style: none;
  margin: 0;
  padding-block: .55rem;
  display: flex;
  gap: .45rem;
  align-items: center;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  /* deep diary trails would otherwise wrap to two lines on a phone */
  overflow-x: auto;
  scrollbar-width: none;
  white-space: nowrap;
}
.crumbs ol::-webkit-scrollbar { display: none; }
.crumbs li { display: flex; gap: .45rem; align-items: center; }
.crumbs li + li::before { content: "▸"; color: var(--reef); }
.crumbs a { color: var(--ink-soft); text-decoration: none; }
.crumbs a:visited { color: var(--ink-soft); }
.crumbs a:hover { color: var(--deep); text-decoration: underline; }
.crumbs [aria-current="page"] { color: var(--abyss); }

/* ------------------------------------------------------------------- main */

main {
  display: block;
  flex: 1 0 auto;
  padding-block: clamp(1.5rem, 4vw, 2.75rem) var(--sp-8);
}
main.home { padding-block-start: 0; }

.block { margin-block-end: var(--sp-sec); }
.block:last-of-type { margin-block-end: var(--sp-6); }

.page-head { margin-block-end: var(--sp-6); }
.page-head h1 { margin-block-start: .2rem; }
.page-head__count {
  display: block;
  font-family: var(--f-body);
  font-size: var(--fs-sm);
  font-weight: 400;
  letter-spacing: .02em;
  color: var(--ink-soft);
  margin-block-start: .5rem;
}

.eyebrow {
  margin: 0;
  color: var(--drop);
  text-transform: none;
}
/* --drop is 4.36:1 on --shoal, under AA for small text; on the pale band the
   eyebrow steps up to --deep (7.48:1). */
.crumbs .eyebrow, .hero__band .eyebrow { color: var(--deep); }

/* The brass wind-rule: the one warm element on a cool page, which is exactly
   why it registers. It is the direction's answer to 風, not to 海. */
.sec-head {
  display: flex;
  align-items: center;
  gap: .9rem;
  font-size: var(--fs-h2);
  margin-block: 0 var(--sp-4);
}
.sec-head::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, var(--brass), transparent);
}

.note {
  max-width: var(--measure);
  color: var(--ink-soft);
  font-size: var(--fs-sm);
  margin-block-end: var(--sp-4);
}

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

/* No scrim, no darkening, no blur over the photograph — it is the best asset
   the site owns. Contrast is supplied locally by a warm pale band landed on
   the image's own horizon (13.57:1). The aspect-ratio is pinned per
   breakpoint so the crop is known and the band lands on the waterline
   instead of hoping to. */
/* The hero's height is driven by its own content, not by an aspect-ratio.
   Pinning the band to a percentage of an aspect-ratio box means its height
   has to be guessed: guess low and it overhangs the frame, guess high and
   the water disappears — which is exactly what happened at 390px, where a
   215px band inside a 340px frame left ten pixels of sea.

   Instead the two paddings reserve the sky above and the water below, in
   percentages OF THE WIDTH, so the frame keeps its proportions across
   viewports while the band takes exactly the room it needs between them. */
.hero {
  position: relative;
  width: 100%;
  background: var(--sky) url("../img/hero-bg.jpg") center 36% / cover no-repeat;
  padding-block: clamp(84px, 26%, 300px) clamp(54px, 7%, 104px);
}
@media (min-width: 900px) {
  .hero { background-position: center 33%; }
}
.hero::after { position: absolute; inset: auto 0 0; height: 3px; }

.hero__band {
  padding-block: clamp(.9rem, 3vw, 1.5rem) clamp(1.1rem, 4vw, 2rem);
  background: rgb(246 239 226 / .88);
  backdrop-filter: blur(3px) saturate(1.1);
  -webkit-backdrop-filter: blur(3px) saturate(1.1);
  /* the sun-glint: the specular line where light strikes water */
  border-top: 1px solid rgb(255 255 255 / .75);
  box-shadow: 0 -7px 20px -6px rgb(255 255 255 / .6);
}
/* Mandatory, not optional: without it the copy sits on a translucent panel
   over a busy photograph and contrast is guaranteed nowhere. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero__band { background: rgb(246 239 226 / .97); }
}

.hero__band .brand__badge { display: inline-grid; margin-block-end: .6rem; }
.hero__band h1 { font-size: var(--fs-hero); }
.hero__lede {
  margin-block: .5rem 0;
  color: var(--ink-soft);
  font-size: var(--fs-sm);
}

/* the one motion on the site: the wind streak is drawn once, left to right */
.hero__band .wind {
  display: block;
  height: 1px;
  width: min(18rem, 60%);
  margin-block: .7rem .2rem;
  background: linear-gradient(90deg, var(--brass), transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .hero__band .wind {
    transform-origin: left;
    animation: streak .7s cubic-bezier(.2, .7, .3, 1) both;
  }
  @keyframes streak { from { transform: scaleX(0); } to { transform: scaleX(1); } }
}

/* --------------------------------------------------------------- counter */

.counter {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem var(--sp-5);
  align-items: center;
  margin-block: var(--sp-5) var(--sp-6);
  padding: .6rem .9rem;
  background: var(--shoal);
  border: 1px solid var(--lagoon);
  border-radius: var(--radius-sm);
  width: max-content;
  max-width: 100%;
}
.counter__cell { display: inline-flex; align-items: center; gap: .5rem; }
.counter__k { color: var(--deep); }
.counter img { display: block; }

/* ----------------------------------------------------------- card grids */

.cards {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .3rem;
  overflow: hidden;
  background: var(--sail);
  border: 1px solid var(--lagoon);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  text-decoration: none;
  color: var(--abyss);
  box-shadow: var(--shadow-1), var(--shadow-2);
}
.card:visited { color: var(--abyss); }
/* No hover lift. Nineteen cards floating on a light page read as fog; the
   motion here is lateral instead — the depth strip surveys across the top
   edge, like a wake. */
.card::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  height: 2px;
  width: 55%;
  background: var(--waterline);
  background-size: 100% 100%;
  transition: width .3s cubic-bezier(.2, .7, .3, 1);
}
.card:hover::before, .card:focus-visible::before { width: 100%; }
.card:hover { border-color: var(--rule-deep); }

.card .k { color: var(--drop); }
.card .t { font-family: var(--f-display); font-size: 1.05rem; font-weight: 500; letter-spacing: .04em; }
.card .d { font-size: var(--fs-sm); color: var(--ink-soft); }
.card--ext .t::after { content: " ↗"; color: var(--drop); font-size: .82em; }

/* ------------------------------------------------------------------ chips */

.chips { display: flex; flex-wrap: wrap; gap: .5rem; list-style: none; margin: 0; padding: 0; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  /* the tap target is real, not faked: the label is centred inside 44px */
  min-height: 44px;
  padding: .3rem .9rem;
  background: var(--shoal);
  border: 1px solid var(--lagoon);
  border-radius: var(--radius-pill);
  color: var(--deep);
  text-decoration: none;
  white-space: nowrap;
}
.chip:visited { color: var(--deep); }
.chip:hover { background: var(--swell); color: var(--abyss); }
.chip.is-current { background: var(--deep); border-color: var(--deep); color: var(--sail); }
.chip__n { color: var(--ink-soft); }
.chip.is-current .chip__n { color: var(--reef); }
.chip--back::before { content: "◂"; color: var(--drop); }
.chip--year::before { content: "▸"; color: var(--drop); }

.pager { display: flex; flex-wrap: wrap; gap: .5rem; margin-block-start: var(--sp-7); }

/* --------------------------------------------------------- year/month nav */

.tocbars { display: grid; gap: var(--sp-3); }
/* min-width:0 is load-bearing. As a grid item, .tocbar's automatic minimum
   size is min-content, and below 600px the rail is flex-wrap:nowrap — so its
   min-content is every chip laid end to end. Without this the track grows
   past the viewport instead of the rail scrolling inside it, and because
   `body { overflow-x: clip }` also kills page panning, the last month chips
   on the busier years become invisible AND untappable. */
.tocbar { display: flex; gap: .75rem; align-items: flex-start; min-width: 0; }
.tocbar__label {
  flex: 0 0 auto;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  color: var(--ink-soft);
  padding-block: .9rem;
}

@media (max-width: 599px) {
  /* a single panning rail rather than four wrapped rows of chips */
  .tocbar .chips {
    flex-wrap: nowrap;
    min-width: 0;              /* same reason as .tocbar above */
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    /* the block padding keeps a focused chip's 3px outline off the clip edge */
    padding-block: 2px;
    padding-inline-end: 1.5rem;
    mask-image: linear-gradient(90deg, #000 calc(100% - 2rem), transparent);
  }
  .tocbar .chips::-webkit-scrollbar { display: none; }
  .tocbar .chip { scroll-snap-align: start; }
}

/* ---------------------------------------------------------- month heading */

.month {
  display: flex;
  align-items: center;
  gap: .8rem;
  max-width: 58rem;
  font-size: var(--fs-h2);
  margin-block: var(--sp-7) var(--sp-4);
  scroll-margin-block-start: calc(var(--head-total) + 1rem);
}
.month::before {
  content: "";
  width: 11px;
  height: 11px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--sail);
  box-shadow: 0 0 0 2px var(--yr);
}
.month::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, var(--lagoon), transparent);
}

/* ------------------------------------------------------------ diary entry */

/* The sounding line: one spine down the year, with every entry hung off it.
   The column is capped rather than filling the 1120px wrap: the prose inside
   is measured to 40em, so a full-width card would be mostly empty margin —
   and 58rem still holds an 800px screenshot at full size without shrinking
   it. */
.entries {
  position: relative;
  display: grid;
  gap: var(--sp-5);
  max-width: 58rem;
}
/* the year/month rail already provides the space above the first month */
.tocbars + .month { margin-block-start: var(--sp-5); }

@media (min-width: 700px) {
  .entries { padding-inline-start: 1.6rem; }
  .entries::before {
    content: "";
    position: absolute;
    inset-block: .4rem;
    inset-inline-start: 4px;
    width: 2px;
    background: linear-gradient(180deg, var(--reef), var(--deep) 55%, var(--abyss));
  }
  .entry::before {
    content: "";
    position: absolute;
    inset-inline-start: -1.6rem;
    inset-block-start: 1.5rem;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    background: var(--sail);
    box-shadow: 0 0 0 2px var(--yr);
  }
}

.entry {
  position: relative;
  background: var(--sail);
  border: 1px solid var(--lagoon);
  border-radius: var(--radius);
  padding: clamp(1rem, 3vw, 1.6rem);
  box-shadow: var(--shadow-1);
  scroll-margin-block-start: calc(var(--head-total) + 1rem);
}

/* The date is the field every entry has and the title is optional, so the
   stamp reads first. The heading still comes first in the DOM — `order`
   moves it visually without disturbing the document outline. */
.entry__head { display: flex; flex-direction: column; margin-block-end: var(--sp-4); }
.entry__title { order: 1; }

.stamp {
  order: 0;
  margin: 0 0 .35rem;
  font-size: var(--fs-stamp);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: .06em;
  line-height: 1;
  color: var(--yr);
}
.stamp::after {
  content: "";
  display: block;
  width: 2.4rem;
  height: 1px;
  margin-block-start: .5em;
  background: var(--yr);
}
.entry__title + .stamp { margin-block-end: 0; }
.entry__head:has(.entry__title) .stamp { margin-block-end: .5rem; }

.entry__text { color: var(--abyss); }

/* The log fields the founder wrote at the foot of an entry — 【宿泊地】,
   【画像】 and their variants — set as real fields. An explicit allow-list
   in the build, never a 【.+?】 catch-all. */
.field {
  font-family: var(--f-display);
  font-weight: 500;
  color: var(--brass-ink);
  letter-spacing: .04em;
}
.logrule {
  display: block;
  width: min(14rem, 60%);
  height: 1px;
  margin-block: .2em .8em;
  background: var(--lagoon);
}

/* ------------------------------------------------------------ screenshots */

/* The mat is the consistent object, never the image. That is what tames a
   162px oddity, a 585x42 strip and an 800x600 shot in one row without
   upscaling any of them into mush, and it gives a dark in-game screenshot a
   perceivable edge on a cream page. */
.shots { display: grid; gap: var(--sp-4); margin-block: var(--sp-4) var(--sp-5); }
/* The mat spans the entry, not the prose measure. Capping it at --measure
   (40em ~= 660px) would shrink 58 of the 97 screenshots below their own
   resolution — the opposite of what the no-upscaling rule is protecting. */
.shot { margin: 0; max-width: 100%; }
.shot .mat {
  display: block;
  padding: 8px;
  background: var(--shoal);
  border: 1px solid var(--rule-deep);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
}
/* No CSS `width` here, deliberately. Every one of these carries width= and
   height= attributes, which act as a presentational hint only while CSS
   leaves width alone — so the image lays out at its own pixel size (never
   upscaled, capped by max-width on a narrow screen) and `height: auto`
   derives the rest from the attribute ratio.

   Setting `width: auto` instead throws that ratio away: a lazy image that
   has not arrived yet then has no intrinsic size at all and lays out at
   2x2px, so all 97 screenshots on a diary page start collapsed and shove the
   text down as they load. */
.shot img {
  margin-inline: auto;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--lagoon);
  border-radius: 3px;
  cursor: zoom-in;
}

/* ---------------------------------------------------------------- replies */

.replies { margin-block-start: var(--sp-5); display: grid; gap: .6rem; }
@media (min-width: 600px) { .replies { margin-inline-start: 1.75rem; } }

.reply {
  background: var(--shoal);
  border-inline-start: 3px solid var(--drop);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: .7rem .9rem;
  font-size: var(--fs-sm);
}
.reply__meta { margin: 0 0 .2rem; display: flex; flex-wrap: wrap; gap: .2rem .6rem; align-items: baseline; }
.reply__who { font-weight: 700; color: var(--deep); }
.reply__date { font-family: var(--f-mono); font-size: var(--fs-xs); color: var(--ink-soft); white-space: nowrap; }
.reply__body { margin: 0; }

/* ----------------------------------------------------------- member card */

.profile {
  display: grid;
  gap: var(--sp-4);
  align-items: start;
  background: var(--sail);
  border: 1px solid var(--lagoon);
  border-radius: var(--radius);
  padding: clamp(1rem, 3vw, 1.5rem);
  box-shadow: var(--shadow-1);
}
@media (min-width: 600px) {
  .profile { grid-template-columns: auto 1fr; gap: var(--sp-5); }
}
.profile--noimg { grid-template-columns: 1fr; }

.profile__pic { margin: 0; }
/* The porthole normalises 46x43 through 1024x768 into one shape. Capped at
   96px so a 46px original is never enlarged past its own resolution —
   pushing these bigger for impact would damage the thing the site exists to
   keep. */
.profile__pic img {
  width: clamp(76px, 20vw, 96px);
  aspect-ratio: 1;
  object-fit: cover;
  object-position: 50% 28%;   /* bias up: centre-cropping a game shot
                                 decapitates the character */
  border-radius: 50%;
  background: var(--shoal);
  box-shadow: 0 0 0 1.5px var(--brass), 0 0 0 3px var(--sail),
              inset 0 8px 14px -8px rgb(255 255 255 / .9),
              var(--shadow-2);
}
.profile__say { line-height: var(--lh-jp); max-width: var(--measure); }

/* ------------------------------------------------------------ member list */

.table-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  border-radius: var(--radius);
}
.roster {
  width: 100%;
  border-collapse: separate;   /* `collapse` drops borders off a sticky head */
  border-spacing: 0;
  font-size: var(--fs-sm);
}
.roster caption { caption-side: bottom; }
.roster th, .roster td {
  padding: .6rem .7rem;
  text-align: start;
  border-bottom: 1px solid var(--lagoon);
  vertical-align: top;
}
.roster thead th {
  position: sticky;
  top: var(--head-total);
  z-index: 2;
  background: var(--shoal);
  border-bottom: 2px solid var(--rule-deep);
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--deep);
  white-space: nowrap;
}
/* Zebra is stamped on the row by the build, not derived with nth-of-type: a
   member with a comment occupies two rows and one without occupies one, so
   no CSS cycle survives contact with the data. */
.roster tr { --row-bg: var(--sail); }
.roster tbody .r.is-alt { --row-bg: var(--shoal); }
.roster tbody .r > * { background: var(--row-bg); }
.roster tbody .r:hover > * { background: var(--swell); }
.roster .c-no, .roster .c-date { font-variant-numeric: tabular-nums; white-space: nowrap; }
.roster .c-no { font-weight: 400; color: var(--ink-soft); }
.roster .c-name { font-weight: 500; }
.roster .c-date { color: var(--ink-soft); font-family: var(--f-mono); font-size: var(--fs-xs); }
/* The old table printed the column's own word even when the member had none.
   These are muted, not decorative: 89 cells across the roster carry real text
   ("メール", "HP", "—"), so they take --ink-soft, which clears AA on the plain
   row, the zebra row and the hover fill alike (6.62 / 6.03 / 5.14:1).
   --rule-deep is 3.35:1 and belongs to borders, never to words. */
.roster .is-none { color: var(--ink-soft); }
/* メールアドレスは伏せ字で掲載する（本人の連絡先保護のため） */
.roster .is-masked { color: var(--ink-soft); font-family: var(--f-mono); font-size: var(--fs-xs); white-space: nowrap; }

/* メンバー一覧の注記 */
.roster-note { margin: 0 0 12px; color: var(--ink-soft); font-size: var(--fs-xs); line-height: 1.8; }


.r-note > td {
  background: #fffaf0;
  border-bottom: 1px solid var(--lagoon);
  padding-block: .55rem .7rem;
  color: var(--ink-soft);
}
.r-note__in { display: block; max-width: 62rem; }
.r-note__k {
  display: inline-block;
  margin-inline-end: .6rem;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .08em;
  color: var(--brass-ink);
}
.r--solo > * { border-bottom-width: 1px; }

.scroll-hint {
  margin: .5rem 0 0;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  text-align: center;
}

@media (max-width: 699px) {
  /* A chart strip that pans sideways with the No. column frozen. Not a stack
     of cards: display:block on table elements strips the table semantics out
     of the accessibility tree, and 39 stacked blocks lose the answer to
     "whose row am I reading?". */
  .table-scroll { scroll-snap-type: x proximity; }
  /* width:100% would make the auto layout share 350px between seven columns
     and hyphen-wrap "イスパニア" into three lines. Letting the table take its
     natural width instead hands the overflow to the wrapper, which is what
     the wrapper is for. */
  .roster { width: max-content; min-width: 100%; }
  .roster td, .roster th { white-space: nowrap; }
  .r-note > td { white-space: normal; }
  /* Only the header cell and a member row's No. cell freeze. A blanket
     `td:first-child` would also catch the comment row's colspan cell — which
     is the whole table wide, so freezing it does nothing useful, while its
     (0,2,1) specificity would repaint the cream comment tint as a member row
     and hang a stray vertical shadow off the left edge. */
  .roster thead th:first-child,
  .roster tbody .r > :first-child {
    position: sticky;
    inset-inline-start: 0;
    background: var(--row-bg);
    /* the shadow lives on the frozen cell, not the wrapper: a wrapper
       gradient is painted over by the table's own opaque cells */
    box-shadow: 6px 0 10px -8px rgb(11 83 114 / .35);
    min-width: 3rem;
  }
  /* Below 700px the wrapper is the scrollport, so `top: var(--head-h)` is
     measured against a box that never scrolls vertically — the header row is
     simply shunted 56px down and paints over member #1. The offset only makes
     sense when the viewport is the scrollport, which is the >=700px case. */
  .roster thead th { top: 0; scroll-snap-align: start; }
  .roster thead th:first-child { z-index: 3; background: var(--shoal); }
  .roster tbody th:first-child { z-index: 1; }
  /* the comment spans the whole table, so it is pinned to the left edge and
     kept readable instead of running off to a width nobody will scroll to */
  .r-note__in {
    position: sticky;
    inset-inline-start: 0;
    width: min(84vw, 34rem);
  }
}
@media (min-width: 700px) {
  /* released so the sticky <thead> parks against the viewport under the
     masthead; inside an overflow-x:auto box it would stick to the wrapper */
  .table-scroll { overflow: visible; }
  .scroll-hint { display: none; }
}

/* ------------------------------------------------------------ about page */

.feature { display: grid; gap: var(--sp-4); align-items: start; }
@media (min-width: 800px) {
  .feature { grid-template-columns: 400px 1fr; gap: var(--sp-6); }
  .feature--flip { grid-template-columns: 1fr 400px; }
  .feature--flip .feature__art { order: 1; }
}
.feature__art { margin: 0; }
/* Same rule as the diary screenshots: no CSS width, so the 400x300 source
   governs and is never blown up. `width: 100%` stretched these to 1.78x
   between roughly 440px and 800px, where the column is wider than the photo. */
.feature__art img {
  max-width: 100%;
  border-radius: var(--radius-sm);
  border: 1px solid var(--rule-deep);
  box-shadow: var(--shadow-1), var(--shadow-2);
}
.feature__txt { line-height: var(--lh-jp); max-width: var(--measure); }
/* the 【…】 that opens each panel is a heading in all but markup */
.field--head { font-size: 1.08em; }

/* ------------------------------------------------------------- links page */

.linkcards { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.linkcard {
  display: grid;
  gap: .1rem .9rem;
  padding: .9rem .2rem;
  border-bottom: 1px solid var(--lagoon);
}
@media (min-width: 760px) {
  .linkcard { grid-template-columns: minmax(16rem, 22rem) 1fr; align-items: baseline; }
}
.linkcard:first-child { border-top: 1px solid var(--lagoon); }
.linkcard__t { font-weight: 500; }
.linkcard__d { margin: 0; color: var(--ink-soft); font-size: var(--fs-sm); }

/* ------------------------------------------------------------------ footer */

.site-foot {
  position: relative;
  background: var(--trench);
  color: var(--foam);
  margin-block-start: auto;
}
.site-foot::before { position: absolute; inset: -3px 0 auto; height: 3px; }

.site-foot__grid {
  display: grid;
  gap: var(--sp-5);
  padding-block: var(--sp-6) var(--sp-4);
}
@media (min-width: 700px) {
  .site-foot__grid { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
}
.site-foot h2 {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--sail);
  margin-block-end: .7rem;
  padding-block-end: .5rem;
  border-bottom: 1px solid rgb(192 138 46 / .22);
}
.site-foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .4rem; }
.site-foot a { color: var(--foam); text-decoration: none; font-size: var(--fs-sm); }
.site-foot a:visited { color: var(--foam); }
.site-foot a:hover { color: var(--sail); text-decoration: underline; }
.site-foot :focus-visible { outline-color: #7fe3e0; }

.site-foot__base {
  border-top: 1px solid rgb(143 180 194 / .18);
  padding-block: var(--sp-4) var(--sp-6);
  display: grid;
  gap: .8rem 1rem;
  grid-template-columns: auto 1fr;
  align-items: start;
}
@media (min-width: 700px) {
  .site-foot__base { grid-template-columns: auto 1fr auto; }
}
.foot-mark { display: block; opacity: .75; padding-block-start: .3rem; }
.foot-mark img { width: 40px; height: 25px; }

.legal { min-width: 0; }
.legal p { margin: 0 0 .35rem; font-size: var(--fs-xs); line-height: 1.8; color: var(--foam); }
.legal p:last-child { margin-bottom: 0; }
.legal .legal-copy { color: var(--sail); }

/* Scoped to .site-foot so it outranks `.site-foot a { color: var(--foam) }`
   (0,1,1). Unscoped, .to-top (0,1,0) lost, and the chip's label sat at
   3.80:1 on its own --deep fill instead of the intended 8.20:1. */
.site-foot .to-top {
  grid-column: 2;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 44px;
  padding: .3rem 1rem;
  background: var(--deep);
  border-radius: var(--radius-pill);
  color: var(--sail);
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .12em;
  text-decoration: none;
}
.site-foot .to-top:visited { color: var(--sail); }
.site-foot .to-top:hover { background: var(--drop); color: var(--sail); text-decoration: none; }
@media (min-width: 700px) {
  .site-foot .to-top { grid-column: 3; justify-self: end; align-self: center; }
}

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

/* A grid so the close button is a row of the dialog rather than something
   hung outside it, and so the figure gets whatever height is left over. */
.lb {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: min(96vw, 1200px);
  max-height: 92svh;
  overflow: visible;
  color: var(--sail);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: .5rem;
}
.lb:not([open]) { display: none; }
.lb::backdrop { background: rgb(4 26 43 / .86); }
.lb__fig {
  margin: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: .6rem;
  justify-items: center;
}
.lb__fig img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--trench);
  touch-action: pinch-zoom;
}
.lb__cap { font-size: var(--fs-xs); color: var(--foam); text-align: center; }
/* Inside the dialog, not floating above it. Hanging it at inset-block-start
   -2.9rem put it off the top of the screen on any short viewport (a landscape
   phone), and since it is the element that takes focus when the lightbox
   opens, the focus ring went with it. */
.lb__close {
  justify-self: end;
  min-height: 44px;
  padding: .3rem 1rem;
  background: var(--deep);
  color: var(--sail);
  border: 1px solid var(--drop);
  border-radius: var(--radius-pill);
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .12em;
  cursor: pointer;
}
.lb__close:hover { background: var(--drop); }
.lb :focus-visible { outline-color: #7fe3e0; }

/* ------------------------------------------------------------ motion, print */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

@media print {
  .site-head, .crumbs, .site-foot, .pager, .tocbars, .nav-toggle,
  .scroll-hint, .skip { display: none !important; }
  body { background: #fff; }
  .entry, .card, .profile { break-inside: avoid; box-shadow: none; }
  .table-scroll { overflow: visible; }
  a { color: var(--abyss); }
}


/* 権利・削除依頼の注記（第三者が書いたページに置く） */
.rights-note {
  margin: 0 0 18px;
  padding: 10px 14px;
  border-left: 3px solid var(--accent, #7a5c2e);
  background: rgba(128, 128, 128, 0.08);
  font-size: 13px;
  line-height: 1.85;
}
