/*
  Design system: warm editorial.
  Deliberately not using Inter, not using a blue/purple gradient, not using
  three-equal-card grids. A serif display face carries headings; a plain
  system sans carries body text. One accent colour (rust/terracotta), used
  sparingly. Layout favours an asymmetric, left-aligned editorial rhythm
  over centered hero sections.
*/

:root {
  --paper: #faf6f0;
  --paper-dim: #f1ebe1;
  --ink: #211c16;
  --ink-soft: #4a423a;
  --line: #ddd3c4;
  --accent: #c1541c;
  --accent-dark: #964011;
  --accent-soft: #f1d9c9;
  --danger: #a3261b;
  --danger-dark: #7a1c14;
  --career: #964011;
  --personal: #4a5a40;
  --hobby: #3a5a78;
  --project: #7a5230;

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --sans: -apple-system, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --measure: 42rem;
  --wrap: 76rem;
  --axis-hint-width: 2.75rem;
}

* {
  box-sizing: border-box;
}

html {
  font-size: 18px;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Classic "sticky footer": body is always at least one viewport tall and
     stacks header/main/footer vertically; main grows to fill whatever
     space the page's actual content doesn't use, so the footer sits right
     at the bottom of the viewport on short pages (e.g. Privacy, a Projects
     table with few rows), instead of floating up right under the content.
     On pages with enough content to fill or exceed the viewport, this has
     no effect at all - the footer just follows the content as normal. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

body > main {
  flex: 1 0 auto;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: var(--accent-dark);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

a:hover {
  color: var(--accent);
}

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 600;
  line-height: 1.15;
  margin: 0 0 0.5em;
  color: var(--ink);
}

h1 { font-size: 2.6rem; letter-spacing: -0.01em; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.3rem; }

p { margin: 0 0 1.1em; }

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 1.5rem;
}

.measure {
  max-width: var(--measure);
}

/* Clearfix so a floated content image (see below) never collapses the
   height of the article/page container it sits in, even when it's the
   last thing inside. */
.measure::after {
  content: "";
  display: table;
  clear: both;
}

/* ------------------------------------------------------- content images */
/* Plain `![alt](/static/img/x.png)` markdown images (screenshots etc.) keep
   the existing plain, full-width look with no extra markup needed.
   To position and size a photo like a framed print, add a position class
   and, optionally, a size class via Markdown's attribute-list syntax
   (enabled by the "extra" extension), directly after the image with no
   space in between, e.g.:

     ![Portrait in the lab](/static/img/lab.jpg){: .img-right .img-medium}

   Position: .img-left, .img-right (floats text alongside), .img-center
   (centered on its own line). Size: .img-small / .img-medium / .img-large
   (default is medium if a position class is used but no size is given).

   Want the frame but not a position/size change (i.e. keep the image
   full-width and in the normal document flow, same as a plain image)? Use
   .img-framed on its own instead:

     ![Portrait in the lab](/static/img/lab.jpg){: .img-framed}
*/
.measure img.img-left,
.measure img.img-right,
.measure img.img-center,
.measure img.img-framed {
  border: 1px solid var(--ink-soft);
  background: var(--paper-dim);
  padding: 0.6rem;
  box-sizing: border-box;
  box-shadow: 0 3px 12px rgba(33, 28, 22, 0.12);
  margin-top: 0.3rem;
  margin-bottom: 1.2rem;
}

.measure img.img-left {
  float: left;
  margin-right: 1.8rem;
}

.measure img.img-right {
  float: right;
  margin-left: 1.8rem;
}

.measure img.img-center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.measure img.img-left:not(.img-small):not(.img-large),
.measure img.img-right:not(.img-small):not(.img-large),
.measure img.img-center:not(.img-small):not(.img-large) {
  width: 50%;
}

.measure img.img-small { width: 33%; }
.measure img.img-large { width: 75%; }

@media (max-width: 620px) {
  .measure img.img-left,
  .measure img.img-right {
    float: none;
    display: block;
    width: 70% !important;
    margin-left: auto;
    margin-right: auto;
  }
}

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

.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  position: sticky;
  top: 0;
  z-index: 10;
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding-top: 1.1rem;
  padding-bottom: 1.1rem;
  flex-wrap: wrap;
}

.brand {
  font-family: var(--serif);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
}

.site-nav {
  display: flex;
  gap: 1.25rem;
}

.site-nav a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.95rem;
}

.site-nav a:hover {
  color: var(--accent);
}

.lang-switch {
  display: flex;
  gap: 0.5rem;
  font-size: 0.8rem;
  border-left: 1px solid var(--line);
  padding-left: 1rem;
}

.lang-switch a {
  text-decoration: none;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
}

.lang-switch a.active {
  color: var(--accent-dark);
  font-weight: 600;
}

.account {
  font-size: 0.9rem;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--accent-dark);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
}

.link-button:hover {
  color: var(--accent);
}

/* ---------------------------------------------------------------- flash */

.flash-messages {
  padding-top: 1rem;
}

.flash {
  padding: 0.75rem 1rem;
  border-radius: 2px;
  font-size: 0.95rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
}

.flash-error {
  border-left-color: #8a2a2a;
  background: #f3dede;
}

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

.hero {
  padding: 3.5rem 0 2.5rem;
  border-bottom: 1px solid var(--line);
}

/* This border only makes sense as a divider between the hero and the
   timeline widget right below it. Without the timeline (SITE_MODE=projects,
   see home()/home.html), there's nothing directly under the hero but empty
   space down to the footer, so the line would just hang there on its own -
   drop it in that case. */
.hero.hero-no-divider {
  border-bottom: none;
}

.hero-grid {
  display: grid;
  grid-template-columns: 1.3fr 0.7fr;
  gap: 3rem;
  align-items: start;
}

/* Unlike the hero, a content page's text (e.g. a short address block on the
   Contact page) rarely fills a wide fr-based column, which left a big dead
   gap between the text and the photo. Size both columns to their actual
   content instead, so they sit close together; any left-over width just
   goes to the page's right margin, matching the site's left-aligned,
   asymmetric layout instead of stretching to fill it. */
.page-grid {
  display: grid;
  grid-template-columns: minmax(0, 24rem) 18rem;
  gap: 2.5rem;
  align-items: start;
}

.hero-kicker {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.8rem;
  color: var(--accent-dark);
  margin-bottom: 0.6rem;
  display: inline-block;
}

.hero-photo,
.page-photo {
  border: 1px solid var(--line);
  background: var(--paper-dim);
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  font-size: 0.85rem;
  text-align: center;
  padding: 1rem;
  overflow: hidden;
}

.hero-photo.has-photo,
.page-photo.has-photo {
  padding: 0.6rem;
  border-color: var(--ink-soft);
  box-shadow: 0 3px 12px rgba(33, 28, 22, 0.12);
}

.hero-photo img,
.page-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border: 1px solid var(--line);
}

@media (max-width: 780px) {
  .hero-grid,
  .page-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------- timeline */

.timeline-section {
  padding: 3rem 0;
}

/* On the dedicated /timeline page (not the home page's embedded widget),
   the heading, filters and axis stick right below the header and stay put
   while the rest of the page - the entry list, then the footer - scrolls
   underneath them normally, same as any other page. This is a second
   sticky element stacked below the already-sticky header, so it needs a
   "top" offset equal to the header's actual height; --header-height is set
   by a small script (static/js/timeline.js) since the header's rendered
   height can vary (e.g. its nav wrapping to two lines on narrow screens).
   The fallback value covers the no-JS case. */
body.page-timeline .timeline-sticky-top {
  position: sticky;
  top: var(--header-height, 4.5rem);
  z-index: 5;
  background: var(--paper);
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--line);
}

.timeline-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.timeline-filters {
  display: inline-block;
  margin: 0.5rem 0 1.3rem;
}

.timeline-filters summary {
  cursor: pointer;
  list-style: none;
  font-size: 0.78rem;
  color: var(--ink-soft);
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.timeline-filters summary::-webkit-details-marker {
  display: none;
}

.timeline-filters summary::before {
  content: "+";
  font-family: var(--serif);
  color: var(--accent-dark);
  width: 1em;
}

.timeline-filters[open] summary::before {
  content: "\2212";
}

.timeline-filters form {
  margin-top: 0.5rem;
  padding: 0.4rem 0.7rem;
  background: var(--paper-dim);
  border: 1px solid var(--line);
  display: inline-block;
}

.timeline-filters fieldset {
  border: none;
  display: flex;
  gap: 0.7rem;
  padding: 0;
  margin: 0;
  flex-wrap: wrap;
  align-items: center;
}

.timeline-filters label {
  font-size: 0.85rem;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.timeline-filters button {
  padding: 0.3rem 0.85rem;
  font-size: 0.85rem;
}

.cat-dot {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
}

.cat-career { background: var(--career); }
.cat-personal { background: var(--personal); }
.cat-hobby { background: var(--hobby); }
.cat-project { background: var(--project); }

.axis-wrapper {
  position: relative;
  margin-bottom: 1rem;
}

.axis-scroller {
  overflow-x: auto;
  cursor: grab;
  scrollbar-width: none; /* Firefox: no scrollbar, the arrow hints indicate scrollability instead */
}

.axis-scroller::-webkit-scrollbar {
  display: none; /* Chrome/Safari/Edge */
}

.axis-scroller.is-dragging {
  cursor: grabbing;
  user-select: none;
}

.axis-hint {
  position: absolute;
  top: 0;
  height: 4.5rem;
  width: var(--axis-hint-width);
  display: flex;
  align-items: center;
  font-family: var(--serif);
  font-size: 1.7rem;
  line-height: 1;
  color: var(--accent-dark);
  z-index: 2;
  border: none;
  padding: 0;
  cursor: pointer;
  /* Without this, some browsers (notably on Linux, following the native
     GTK/Qt theme) still draw a native button hover/press highlight box
     underneath our own styling, since border/background alone don't fully
     opt a <button> out of themed native rendering. */
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-color: transparent;
  box-shadow: none;
}

.axis-hint:hover,
.axis-hint:active,
.axis-hint:focus {
  background-color: transparent;
  box-shadow: none;
}

.axis-hint:hover {
  color: var(--accent);
}

.axis-hint:disabled {
  color: var(--ink-soft);
  opacity: 0.35;
  cursor: default;
}

.axis-hint-left {
  left: 0;
  justify-content: flex-start;
  padding-left: 0.1rem;
  background: linear-gradient(to right, var(--paper) 25%, transparent 100%);
}

.axis-hint-right {
  right: 0;
  justify-content: flex-end;
  padding-right: 0.1rem;
  background: linear-gradient(to left, var(--paper) 25%, transparent 100%);
}

.axis-track {
  position: relative;
  min-width: 900px;
  height: 4.5rem;
  /* Clear the fade hints at both ends (--axis-hint-width) plus a little
     breathing room, so the first/last year markers aren't dimmed by them. */
  margin: 0 calc(var(--axis-hint-width) + 0.75rem);
}

.axis-line {
  position: absolute;
  left: 0;
  right: 0;
  top: 2.1rem;
  height: 2px;
  background: var(--line);
}

.axis-marker {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-decoration: none;
  scroll-margin-top: 6rem;
  cursor: pointer;
}

.axis-marker .dot {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  border: 2px solid var(--paper);
  box-shadow: 0 0 0 1px var(--line);
  margin-top: 1.65rem;
}

.axis-marker:hover .dot,
.axis-marker:focus .dot {
  box-shadow: 0 0 0 2px var(--accent);
}

.axis-marker .yr {
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin-top: 0.35rem;
  white-space: nowrap;
}

.timeline-entries {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.timeline-entry {
  border: 1px solid var(--line);
  background: #fff;
  padding: 0;
  scroll-margin-top: 6rem;
}

.timeline-entry summary {
  cursor: pointer;
  list-style: none;
  padding: 1rem 1.2rem;
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
  flex-wrap: wrap;
}

.timeline-entry summary::-webkit-details-marker {
  display: none;
}

.timeline-entry summary::before {
  content: "+";
  font-family: var(--serif);
  color: var(--accent-dark);
  width: 1em;
}

.timeline-entry[open] summary::before {
  content: "\2212";
}

.entry-dates {
  font-family: var(--serif);
  font-weight: 600;
  min-width: 7.5rem;
}

.entry-title {
  color: var(--ink);
  font-weight: 600;
}

.entry-cat {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  margin-left: auto;
}

.entry-body {
  padding: 0 1.2rem 1.2rem 1.2rem;
  border-top: 1px solid var(--paper-dim);
}

/* Teaser text and the "read more" link share one row instead of stacking
   the link on its own line below the teaser, so expanding an entry adds as
   little extra height as possible. If the teaser is short, both end up on
   the same visual line; if it wraps, the link still sits to the right of
   the teaser block rather than under it. */
.entry-body-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
}

.entry-body-row p {
  margin: 0;
}

.entry-read-more {
  font-size: 0.85rem;
  white-space: nowrap;
  flex-shrink: 0;
  text-decoration: none;
}

.entry-read-more:hover {
  text-decoration: underline;
}

.entry-locked {
  padding: 0 1.2rem 1.2rem 1.2rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* --------------------------------------------------------- projects table */
/* The simpler stand-in for the full timeline (SITE_MODE=projects): a plain
   table instead of the expandable axis/entries widget, same warm paper
   palette as the rest of the site rather than the admin theme's colours. */

.projects-table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.5rem 0 3rem;
}

.projects-table th,
.projects-table td {
  text-align: left;
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.projects-table th {
  color: var(--ink-soft);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}

.projects-table .col-period {
  font-family: var(--serif);
  font-weight: 600;
  white-space: nowrap;
}

.projects-table .col-project {
  font-weight: 600;
}

.projects-table .lock-hint {
  font-weight: 400;
  font-size: 0.8rem;
  margin-left: 0.4rem;
}

.projects-table .col-description {
  color: var(--ink-soft);
}

@media (max-width: 620px) {
  .projects-table thead {
    display: none;
  }
  .projects-table tr {
    display: block;
    padding: 0.8rem 0;
    border-bottom: 1px solid var(--line);
  }
  .projects-table td {
    display: block;
    padding: 0.15rem 0;
    border-bottom: none;
  }
}

/* -------------------------------------------------------------- sections */

.numbered-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.75rem;
}

.numbered-list li {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: 1rem;
}

.numbered-list .num {
  font-family: var(--serif);
  font-size: 1.6rem;
  color: var(--accent-dark);
}

section {
  padding: 2.5rem 0;
}

section + section {
  border-top: 1px solid var(--line);
}

.cta {
  display: inline-block;
  border: 1px solid var(--ink);
  padding: 0.6rem 1.2rem;
  text-decoration: none;
  color: var(--ink);
  font-family: var(--serif);
}

.cta:hover {
  background: var(--ink);
  color: var(--paper);
}

.protected-email {
  margin-top: 1.5rem;
  font-family: var(--sans);
}

.protected-email a {
  font-weight: 600;
}

/* ----------------------------------------------------------------- form */

.form-field {
  margin-bottom: 1.1rem;
}

.form-field label {
  display: block;
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 0.3rem;
}

input[type="text"],
input[type="password"],
input[type="date"],
input[type="number"],
textarea,
select {
  width: 100%;
  font: inherit;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
}

textarea {
  min-height: 10rem;
  font-family: "Courier New", monospace;
  font-size: 0.9rem;
  line-height: 1.5;
}

button, .button {
  font: inherit;
  background: var(--ink);
  color: var(--paper);
  border: none;
  padding: 0.55rem 1.1rem;
  cursor: pointer;
}

button:hover, .button:hover {
  background: var(--accent-dark);
}

.button-outline {
  background: none;
  color: var(--ink);
  border: 1px solid var(--ink);
}

/* Destructive actions (admin "Delete"): the outline variant sits on the edit
   form, the solid one on the confirmation page. */
.button-danger {
  background: var(--danger);
  color: var(--paper);
}

.button-danger:hover {
  background: var(--danger-dark);
}

.button-danger-outline {
  background: none;
  color: var(--danger);
  border: 1px solid var(--danger);
}

.button-danger-outline:hover {
  background: var(--danger);
  color: var(--paper);
}

.checkbox-field {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.checkbox-field input {
  width: auto;
}

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

.site-footer {
  border-top: 1px solid var(--line);
  padding: 2rem 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
}

/* Deliberately understated -- same muted colour as the surrounding text,
   only picking up an underline on hover, so the privacy link doesn't
   compete for attention. */
.site-footer a {
  color: var(--ink-soft);
  text-decoration: none;
}

.site-footer a:hover {
  text-decoration: underline;
}

/* --------------------------------------------------------------- errors */

.error-page {
  padding: 5rem 0;
  text-align: left;
}

/* ----------------------------------------------------------------- auth */

.login-form {
  max-width: 24rem;
  margin: 2rem 0;
}

/* ---------------------------------------------------------------- admin */

.admin-body {
  background: var(--paper-dim);
}

.admin-header {
  background: var(--ink);
  color: var(--paper);
  padding: 1rem 0;
}

.admin-header .wrap {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.admin-header a {
  color: var(--paper);
  text-decoration: none;
}

.admin-header a:hover {
  color: var(--accent-soft);
}

.admin-main {
  padding: 2rem 0 4rem;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  margin-bottom: 2rem;
}

.admin-table th, .admin-table td {
  text-align: left;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.9rem;
}

.admin-table th {
  color: var(--ink-soft);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}

.status-tag {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 2px;
  font-size: 0.75rem;
  background: var(--paper-dim);
  border: 1px solid var(--line);
}

.status-tag.stale {
  background: #f3dede;
  border-color: #d9b3b3;
  color: #7a2a2a;
}

.status-tag.ai_draft {
  background: #eaf0e6;
  border-color: #c8d9be;
  color: #3d5a2a;
}

.admin-card {
  background: #fff;
  border: 1px solid var(--line);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.meta-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

@media (max-width: 900px) {
  .meta-grid { grid-template-columns: repeat(2, 1fr); }
}

.locale-tabs input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.locale-tab-labels {
  display: flex;
  gap: 0.4rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1rem;
}

.locale-tab-labels label {
  padding: 0.5rem 1rem;
  cursor: pointer;
  border: 1px solid var(--line);
  border-bottom: none;
  background: var(--paper-dim);
  font-size: 0.9rem;
  margin-bottom: -1px;
}

#tab-cs:checked ~ .locale-tab-labels label[for="tab-cs"],
#tab-en:checked ~ .locale-tab-labels label[for="tab-en"] {
  background: #fff;
  font-weight: 600;
}

.locale-panel {
  display: none;
}

#tab-cs:checked ~ .locale-panels .locale-panel[data-locale="cs"],
#tab-en:checked ~ .locale-panels .locale-panel[data-locale="en"] {
  display: block;
}

.translate-row {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin-bottom: 1rem;
  padding: 0.7rem;
  background: var(--paper-dim);
  border: 1px solid var(--line);
  font-size: 0.85rem;
}

.translate-row select {
  width: auto;
}
