* {
    box-sizing: border-box;
}

/* the [hidden] attribute is only display:none in the user-agent stylesheet, so
   any author rule setting display (.card is display:block) silently beats it and
   the element stays visible. !important is the standard fix. */
[hidden] {
    display: none !important;
}

html {
    font-size: 125%;
}


/*  variables  */

:root {
    --light-bg:     #dedede;
    --light-ink:    #151514;
    --light-green:  #99c7bb;
    --light-purple: #c0b8d6;
    --light-brick:  #cf9999;
    --light-gold:   #d6c58d;
    --light-orange: #d6938d;
    --light-blue: #8993dc;

    --dark-bg:     #151514;
    --dark-ink:    #dedede;
    --dark-green:  #2f5d50;
    --dark-purple: #4a3d6b;
    --dark-brick:  #6b3d3d;
    --dark-gold:   #6b5a2f;
    --dark-orange: #53281b;
    --dark-blue: #24294e;


    color-scheme: dark;

  /* primary color is read by voronoi to build the palette */
    --primary-color: var(--dark-bg);
    --border-colour: var(--dark-ink);
    --text-colour:   var(--dark-ink);

    --generic-colour: var(--dark-ink);
    --conspiracy-colour: var(--dark-green);
    --politics-colour: var(--dark-purple);
    --art-colour: var(--dark-gold);

    --green-colour:  var(--dark-green);
    --purple-colour: var(--dark-purple);
    --brick-colour:  var(--dark-brick);
    --gold-colour:   var(--dark-gold);
    --orange-colour: var(--dark-orange);
    --blue-colour:   var(--dark-blue);

    --gap: 0.5rem;
    --page-width: 62.5rem;
    --side-width: 11.25rem;
    --panel-pad: 1.25rem;

    --banner-width: 25rem;
    --banner-gap: 3.5rem;

    --section-indent: 1rem;
    --content-height: 26rem;

    /* height of a standard page: the content row plus the fixed furniture above
       and below it (ticker + gap, nav, gap, gap, footer). every page's frame is
       identical apart from the content row, so this is the constant the layout
       is centred against. nudge it if the furniture changes height -- too small
       and every page sits a little low, too large and it sits a little high,
       but all pages stay in step with each other either way. */
    --frame-height: calc(var(--content-height) + 10.25rem);
}

:root[data-theme="light"] {
    color-scheme: light;

    --primary-color: var(--light-bg);
    --border-colour: var(--light-ink);
    --text-colour:   var(--light-ink);

    /* tag colours  maybe replace with reading tags*/
    --generic-colour: var(--light-ink);
    --conspiracy-colour: var(--light-green);
    --politics-colour: var(--light-purple);
    --art-colour: var(--light-gold);

    /* colours */
    --green-colour:  var(--light-green);
    --purple-colour: var(--light-purple);
    --brick-colour:  var(--light-brick);
    --gold-colour:   var(--light-gold);
    --orange-colour: var(--light-orange);
    --blue-colour:   var(--light-blue);
}


/*  fonts  */

@font-face {
    font-family: "Domine";
    src: url('/fonts/Domine-Regular.ttf') format('truetype');
    font-display: swap;
}


/*  base elements  */

body {
    margin: 0;
    background-color: var(--primary-color);
    /* the layout is placed against --frame-height, not against .page's real
       height. centring the real height would move the top edge every time a
       grow page came out taller -- and the banner hangs off that top edge, so
       it would visibly jump on every navigation. this way a grow page keeps the
       same top as every other page and simply extends further down.
       max() keeps the old 2.5rem when the viewport is too short to centre. */
    padding-top: max(2.5rem, calc((100vh - var(--frame-height)) / 2));
    padding-bottom: 2.5rem;
    padding-left: 1.25rem;
    padding-right: 1.25rem;
    min-height: 100vh;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    font-family: "Domine", serif;
    font-size: 1rem;
    color: var(--text-colour);
}

a {
    color: var(--text-colour);
}

audio {
    display: block;
    width: 100%;
}


/*  background  */

#bg {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    pointer-events: none;
}


/*  page structure  */

.page {
    position: relative;
    width: 100%;
    max-width: var(--page-width);
}

.banner {
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    margin-bottom: var(--banner-gap);
    margin-left: auto;
    margin-right: auto;
    max-width: var(--banner-width);
}

.banner h1 {
    margin: 0;
    text-align: center;
    font-size: 4rem;
}


.layout {
    display: grid;
    grid-template-columns: var(--side-width) 1fr var(--side-width);
    grid-template-rows: auto var(--content-height, 25rem) auto;
    grid-template-areas:
        "nav     nav      nav"
        "menu    content  extras"
        "footer  footer   footer";
    gap: var(--gap);
}

.layout.full{
    grid-template-areas:
        "nav     nav      nav"
        "content    content  content"
        "footer  footer   footer";
}

/*  growing pages  */

/* `grow: true` in a page's front matter. the content row stops being a fixed
   --content-height box that scrolls internally, and instead sizes to its own
   content with --content-height as a floor -- so the panel is as tall as it
   needs to be and the page does the scrolling. for long lists: blog, projects,
   posts. leave it off and a page keeps the standard panel size. */
.layout.grow {
    grid-template-rows: auto minmax(var(--content-height), auto) auto;
}

/* nothing overflows the row any more, so neither of these should clip or
   capture a scroll -- the panel has to be free to be its full height. */
.layout.grow .content {
    overflow: visible;
}

.layout.grow .panel-body {
    overflow-y: visible;
}


/*  grid areas  */

.nav {
    grid-area: nav;
}


.menu    {
    grid-area: menu;
    display: flex;
    flex-direction: column;
}

.menu-body,
.extras-body,
.panel-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.menu-body > :first-child,
.extras-body > :first-child,
.panel-body > :first-child {
    margin-top: 0;
}

/* these are overflow:auto boxes, so a trailing margin can't collapse out of
   them and counts toward scrollHeight. without this the panel scrolls by the
   last child's margin-bottom (20px for a <p>, --gap for a .card) with nothing
   new to reveal, and the hidden scrollbar gives no hint why. */
.menu-body > :last-child,
.extras-body > :last-child,
.panel-body > :last-child {
    margin-bottom: 0;
}

.content,
.menu,
.extras {
    min-height: 0;
}

.content {
    grid-area: content;
    overflow: hidden;
}


.content > .panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.content > .panel:last-child {
    flex: 1 1 auto;
}

.extras  {
    grid-area: extras;
    display: flex;
    flex-direction: column;
}

.footer  {
    grid-area: footer;
    text-align: center;
}

.p-indent {
    padding-left: 10px;
}

/*  panel colours  */

/* put one of these on any .panel to colour its head and its border.
   nothing structural sets --head-color any more, so a panel's colour is
   whatever the markup says it is. */
.green   { --head-color: var(--green-colour); }
.purple  { --head-color: var(--purple-colour); }
.brick   { --head-color: var(--brick-colour); }
.gold    { --head-color: var(--gold-colour); }
.orange  { --head-color: var(--orange-colour); }
.blue    { --head-color: var(--blue-colour); }
/* no .ink: --border-colour is near-white in dark mode, so text sitting on it
   disappears. every colour above is dark in dark mode and light in light mode,
   which is what keeps --text-colour readable on all of them. */


/*  panels  */

.panel {
    background-color: var(--primary-color);
    border: 1px solid var(--panel-border, var(--head-color, var(--border-colour)));
    padding: var(--panel-pad);
}

.panel .panel-head{
    margin: calc(var(--panel-pad) * -1);
    margin-bottom: var(--panel-pad);
    padding: 0.4rem 0.75rem;
    background: var(--head-color, #2b2b28);
    font-size: 1.1rem;
    letter-spacing: 0.1em;
    font-weight: normal;
}

.panel h2 {
    margin-top: 0;
}

.panel.scrolling-left {
    /*  msg-count must match the number of <p> inside .scrolling-track */
    --msg-time: 15s;
    --msg-count: 4;
    --msg-gap: 60rem;

    overflow: hidden;
    padding: 0;
    margin-bottom: var(--gap);
    background-color: var(--blue-colour);
    border-color: var(--border-colour);
}

.scrolling-mask {
    mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
}

.scrolling-track {
    display: flex;
    width: max-content;
    position: relative;
    animation: scroll-left calc(var(--msg-time) * var(--msg-count)) linear infinite;
    animation-delay: var(--anim-offset, 0s);
}

.scrolling-track p {
    white-space: nowrap;
    margin: 0;
    padding-right: var(--msg-gap);
}


@keyframes scroll-left {
    from { left: 100%; transform: translateX(0); }
    to   { left: 0;    transform: translateX(-100%); }
}

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

.section {
    margin-left: var(--section-indent);
}

.section p {
    margin-left: var(--section-indent);
}

/*  nav  */

.panel.nav {
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
}

.nav ul {
    list-style: none;
    margin: 0;
    padding: 0px;
    display: flex;
    gap: 1.5rem;
    justify-content: center;
    align-items: center;
}

.nav img {
    display: block;
    height: 2.25em;
    width: auto;
    border: 2px solid var(--border-colour);
    border-radius: 5px;
}


/* cards */
.card {
    display: block;
    border: 1px solid var(--active-filter-colour, var(--border-colour));
    padding: 0.75rem 1rem;
    margin-bottom: var(--gap);
    color: inherit;
    text-decoration: none;
}

.card:hover,
.card:focus-visible {
    background-color: color-mix(in srgb, var(--text-colour) 8%, transparent);
}

.card:focus-visible {
    outline: 2px solid var(--text-colour);
    outline-offset: 2px;
}

.card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
}

.card-head h3 {
    margin: 0;
}

.card-summary {
    margin: 0.4rem 0 0;
}

.card-date {
    margin: 0.4rem 0 0;
    font-size: 0.85rem;
    opacity: 0.7;
}

.tag {
    flex: none;
    align-self: center;
    /* same utility classes as panels: .tag.purple, .tag.gold, ... */
    background-color: var(--head-color, var(--blue-colour));
    padding: 0.15rem 0.6rem;
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    white-space: nowrap;
}

.change{
    border: 1px solid var(--border-colour);
}

/*  theme toggle  */

.theme-toggle {
    --overhang: 35%;

    position: absolute;
    top: -1px;
    right: -1px;
    transform: translate(var(--overhang), calc(var(--overhang) * -1));

    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--text-colour);
    cursor: pointer;
}


.theme-face {
    display: none;
    align-items: center;
    gap: 0.4em;
}

.theme-face img {
    display: inline-block;
    height: 6em;
    width: auto;
    z-index: 2;
}

.theme-face-dark {
    display: inline-flex;
}

:root[data-theme="light"] .theme-face-dark {
    display: none;
}

:root[data-theme="light"] .theme-face-light {
    display: inline-flex;
}


/*  stuff/extra  */

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--gap);
}

.scroll {
    overflow: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}


/*  responsive  */

@media (max-width: 700px) {
  .banner {
    position: relative;
    max-width: none;
  }

  .layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      "nav"
      "menu"
      "content"
      "extras"
      "footer";
  }
}


/*  swup  */
/* removed transitions cause instant page swaps looks cleaner */

/*  blog filters  */

.blog-toolbar {
    /* a flex item of .panel now, sitting between the head and the scroll body:
       never let it shrink, or the buttons squash instead of the cards scrolling. */
    flex: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    margin-bottom: 1rem;
}

.blog-toolbar h4 {
    margin: 0;
}

.filters {
    --head-color: initial;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0;
}

.filter {
    font: inherit;
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    color: var(--text-colour);
    background: none;
    border: 1px solid var(--head-color, var(--border-colour));
    padding: 0.15rem 0.6rem;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.15s ease, background-color 0.15s ease;
}

.filter:hover,
.filter:focus-visible {
    opacity: 1;
}

.filter.is-active {
    opacity: 1;
    background-color: var(--head-color, var(--blue-colour));
}


.filter[data-filter="all"].is-active {
    background: none;
    border-color: var(--text-colour);
}

.no-matches {
    opacity: 0.7;
}

/*  page transitions  */

@view-transition {
    navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 0.22s;
    animation-timing-function: ease;
}


.banner         { view-transition-name: banner; }
.scrolling-left { view-transition-name: ticker; }
.nav            { view-transition-name: nav; }
.menu           { view-transition-name: menu; }
.extras         { view-transition-name: extras; }
.footer         { view-transition-name: footer; }

@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation: none;
    }
}
