/* Vertical rhythm lives here — raise these three to loosen the whole page,
   lower them to tighten it further. Everything below refers back to them. */
:root {
    color-scheme: light;
    --color-bg: #f2f4f2;
    --color-surface: #ffffff;
    --color-text: #292d2a;
    --color-muted: #626963;
    --color-border: #d7dcd6;
    --color-border-soft: #e6e9e5;
    --color-hover: #f2f4f1;
    --color-link: #337ab7;
    --color-link-hover: #23527c;
    --color-accent: #6da872;
    --color-accent-soft: #dfe8dd;
    --content-gutter: clamp(1.25rem, 5vw, 2rem);
    --space-section: 1.35em;
    --space-block: 0.5em;
    --space-text: 0.22em;
}

/* basic html elements */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

a {
    text-decoration: none;
}

body {
    margin: 0;
    color: var(--color-text);
    background-color: var(--color-bg);
    /* pin the generic family: <html lang> now changes with the language
       switcher, and without this the browser's per-language default font
       would restyle the whole page on every switch. */
    font-family: Georgia, "Times New Roman", "Noto Serif TC", serif;
    line-height: 1.52;
    -webkit-font-smoothing: antialiased;
}

p {
    margin-block-start: var(--space-text);
    margin-block-end: var(--space-text);
    overflow-wrap: break-word;
}

h1 {
    margin: 0.15em 0 0.05em;
    font-size: clamp(1.8rem, 6vw, 2.15rem);
    line-height: 1.25;
    text-wrap: balance;
}

.profile-name ruby {
    ruby-align: center;
    ruby-position: over;
}

.profile-name rt {
    color: var(--color-muted);
    /* Arial has proper mark anchors for the decomposed Tai-lo N + circumflex.
       The macOS system UI font visually drifts this mark toward the g. */
    font-family: Arial, "Liberation Sans", sans-serif;
    font-size: 0.38em;
    font-weight: 500;
    letter-spacing: normal;
    line-height: 1.1;
}

.profile-name rt>span {
    display: inline-block;
    white-space: nowrap;
}

.profile-full-name,
.profile-handle {
    white-space: nowrap;
}

h2 {
    margin: 0 0 0.38em;
    font-size: 1.5rem;
    line-height: 1.3;
    text-wrap: balance;
}

h3 {
    margin: 0 0 0.12em;
    font-size: 1.12rem;
    line-height: 1.35;
    text-wrap: balance;
}

ul {
    margin: var(--space-text) 0;
    padding-left: 1.5em;
}

hr {
    margin: 0.85em var(--content-gutter);
    display: block;
    height: 1px;
    border: 0;
    border-top: 1px solid var(--color-border-soft);
}

a {
    color: var(--color-link);
    transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease;
}

a:hover,
a:active {
    color: var(--color-link-hover);
}

:focus-visible {
    outline: 3px solid rgba(51, 122, 183, 0.38);
    outline-offset: 3px;
}

footer {
    text-align: center;
    color: var(--color-muted);
    padding: 0.7em;
    font-size: 0.88rem;
}

pre {
    margin: 0;
    padding: 0.78em 1em;
    font-size: 16px;
    overflow: auto;
}

.skip-link {
    position: fixed;
    top: 0.75rem;
    left: 0.75rem;
    z-index: 10;
    padding: 0.55rem 0.8rem;
    color: var(--color-text);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 3px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
    transform: translateY(calc(-100% - 1rem));
}

.skip-link:focus {
    transform: translateY(0);
}


/* custom class */
.container {
    position: relative;
    /* top margin only has to clear the avatar's 3.5em overhang */
    margin: 5.5em auto 0;
    padding-bottom: 1.5em;
    width: min(720px, calc(100% - 2rem));
    min-height: 256px;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-soft);
    border-radius: 4px;
    box-shadow: 0 16px 44px rgba(36, 41, 46, 0.12);
}

.lang-switch {
    position: absolute;
    top: 0.75em;
    right: 1em;
    /* .avatar-container is a full-width positioned block that comes later in
       the DOM, so without this it paints over the switcher and swallows the
       clicks even though it is visually transparent here. */
    z-index: 1;
    font-size: 14px;
    line-height: 1;
}

.lang-switch button {
    font: inherit;
    color: var(--color-muted);
    background: none;
    border: 0;
    min-height: 2rem;
    padding: 0 0.65em;
    cursor: pointer;
}

.lang-switch button+button {
    border-left: 1px solid var(--color-border-soft);
}

.lang-switch button:hover {
    color: var(--color-text);
}

.lang-switch button[aria-current="true"] {
    color: var(--color-text);
    font-weight: 600;
    cursor: default;
}

.section-nav {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    gap: 0.15rem;
    padding: 0.42rem var(--content-gutter);
    overflow-x: auto;
    background: rgba(255, 255, 255, 0.96);
    border-top: 1px solid var(--color-border-soft);
    border-bottom: 1px solid var(--color-border-soft);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.section-nav::-webkit-scrollbar {
    display: none;
}

.section-nav a {
    flex: 0 0 auto;
    padding: 0.22rem 0.62rem;
    color: var(--color-muted);
    border-radius: 999px;
    font-size: 0.88rem;
    line-height: 1.5;
    white-space: nowrap;
}

.section-nav a:hover {
    color: var(--color-text);
    background: var(--color-hover);
}

.section-nav+.content {
    padding-top: 1.35rem;
}

/* The 8em avatar is centred and overflows the card, so under ~420px there is
   no room left beside it — the switcher drops into the flow under the social
   links instead of sitting unreadably on top of the avatar. The breakpoint
   clears every phone in portrait, since the switcher's width depends on the
   platform's serif metrics and cannot be pinned exactly. */
@media (max-width: 440px) {
    .lang-switch {
        position: static;
        text-align: center;
        margin-top: 0.7em;
    }
}

@media (max-width: 720px) {
    .container {
        margin-top: 4.75em;
        width: calc(100% - 1rem);
    }

    .section-nav {
        padding-inline: 0.6rem;
    }
}

.avatar-container {
    position: relative;
    top: -3.5em;
    margin-bottom: -3.5em;
    text-align: center;
}

.avatar {
    background-color: black;
    border: 4px solid var(--color-surface);
    box-shadow: 0 5px 16px rgba(36, 41, 46, 0.2);
    border-radius: 50%;
    margin: 0px auto;
    width: 7em;
    height: 7em;
    object-fit: cover;
}

.basic-info {
    padding: 0 var(--content-gutter);
    text-align: center;
}

.profile-tagline {
    margin-top: 0.12rem;
    color: #454b46;
    font-size: 1.02rem;
}

.profile-education {
    margin-top: 0.08rem;
    color: var(--color-muted);
    font-size: 0.94rem;
}

.profile-education>b {
    color: var(--color-text);
}

.social-links {
    display: flex;
    justify-content: center;
    gap: 0.2rem;
    margin-top: 0.12rem;
}

.social-links>a {
    display: inline-grid;
    width: 2.5rem;
    height: 2.5rem;
    margin: 0;
    color: var(--color-text) !important;
    border-radius: 50%;
    font-size: 28px !important;
    place-items: center;
}

.social-links>a:hover {
    color: var(--color-muted) !important;
    background: var(--color-hover);
}

/* inline svg icons (replaces font awesome webfonts) */
.icon {
    height: 1em;
    width: auto;
    fill: currentColor;
    vertical-align: -0.125em;
}

.content {
    padding: 0 var(--content-gutter);
    margin-bottom: var(--space-section);
    scroll-margin-top: 4rem;
}

.content>.content {
    padding-inline: 0;
    margin-bottom: var(--space-block);
}

.content>.content>h3 {
    margin-block-start: 0;
    margin-block-end: 0;
}

#ctf-author>.content,
#campus>.content {
    margin: 0;
    padding-block: 0.48rem;
}

#ctf-author>h2+.content,
#campus>h2+.content {
    padding-top: 0.12rem;
}

#ctf-author>.content+.content,
#campus>.content+.content {
    border-top: 1px solid var(--color-border-soft);
}

#ctf-author>.content:last-child,
#campus>.content:last-child {
    padding-bottom: 0;
}

#ctf-author>.content>p {
    margin-top: 0.04rem;
    color: var(--color-muted);
    font-size: 0.92rem;
}

#campus>.content>ul:last-child {
    margin-bottom: 0;
}

#campus>.content li+li {
    margin-top: 0.12rem;
}

.campus-detail {
    color: var(--color-muted);
    font-size: 0.92rem;
}

.education-credential {
    margin: 0.08rem 0 0.25rem;
    color: var(--color-muted);
    font-size: 0.88rem;
    font-style: italic;
    font-weight: 400;
    letter-spacing: 0.01em;
}

.education-credential+ul {
    margin-top: 0.12rem;
}

.event-list {
    --event-date-width: 5.5rem;
    --event-gap: 0.8rem;
    margin: 0.45rem 0 0;
    padding: 0;
    list-style: none;
}

#job .event-list {
    --event-date-width: 7.75rem;
}

.event-list>li {
    display: grid;
    grid-template-columns: var(--event-date-width) minmax(0, 1fr);
    gap: var(--event-gap);
    margin: 0;
    padding: 0.52rem 0;
    border-bottom: 1px solid var(--color-border-soft);
}

.event-list>li:first-child {
    padding-top: 0.25rem;
}

.event-list>li:last-child {
    padding-bottom: 0;
    border-bottom: 0;
}

.event-list--grouped-dates>li {
    padding-block: 0.27rem;
    border-bottom: 0;
}

.event-list--grouped-dates>li:not(.event-list-item--date-continuation):not(:first-child) {
    margin-top: 0.28rem;
    padding-top: 0.58rem;
    border-top: 1px solid var(--color-border-soft);
}

.event-list--grouped-dates>li:first-child {
    padding-top: 0.25rem;
}

.event-list--grouped-dates>li:last-child {
    padding-bottom: 0;
}

.event-date {
    margin: 0;
    padding-top: 0.08rem;
    color: var(--color-muted);
    font-size: 0.82rem;
    font-style: italic;
    font-variant-numeric: tabular-nums;
    font-weight: 400;
    letter-spacing: 0.01em;
    line-height: 1.35;
    text-align: right;
    white-space: nowrap;
}

#job .event-date {
    font-size: 0.78rem;
    font-style: normal;
    letter-spacing: 0;
}

.event-content {
    min-width: 0;
}

.event-meta {
    margin: 0 0 0.06rem;
    color: var(--color-muted);
    font-size: 0.9rem;
    font-style: italic;
    font-weight: 400;
    line-height: 1.32;
    overflow-wrap: anywhere;
}

.event-meta>a {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: var(--color-border);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
}

.event-meta>a:hover,
.event-meta>a:active {
    color: var(--color-link-hover);
    text-decoration-color: currentColor;
}

.event-content>h3 {
    margin: 0;
    font-size: 1.08rem;
    line-height: 1.34;
    overflow-wrap: anywhere;
}

.content>h2::after {
    content: "";
    display: block;
    width: 2rem;
    height: 3px;
    margin-top: 0.25rem;
    background: var(--color-accent);
    border-radius: 999px;
}

.code-block {
    color: var(--color-text);
    background: #f4f3f1;
    border: 1px solid #e2e3df;
    border-radius: 3px;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
    font-size: clamp(0.78rem, 2.4vw, 1rem);
    line-height: 1.45;
}

.more {
    text-align: center;
    display: block;
    /* full width so it lines up with the repo cards above it */
    color: #4f5650;
    background-color: #f0f2ef;
    padding: 0.52em;
    border-radius: 3px;
    font-weight: 600;
}

.more:hover {
    color: var(--color-text);
    background-color: #e4e8e2;
}

.more:active {
    color: var(--color-text);
    background-color: #d9ded7;
}

.gh-repo {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 3px;
    padding: 0.65em 0.85em;
    /* no side margin: the cards line up with the section heading instead of
       being indented a further 1em inside .content's padding */
    margin: 0 0 var(--space-block);
    transition: border-color 150ms ease, box-shadow 150ms ease;
}

.gh-repo:hover,
.gh-repo:focus-within {
    border-color: #c4cbc4;
    box-shadow: 0 3px 10px rgba(36, 41, 46, 0.06);
}

.gh-repo .name {
    font-size: 18px;
    font-weight: 600;
    line-height: 1.25;
    color: var(--color-text);
    overflow-wrap: anywhere;
}

.gh-repo .description {
    color: var(--color-muted);
    margin-bottom: 0.3em;
}

.gh-repo .details {
    display: flex;
    flex-wrap: wrap;
    gap: 0.18rem 1rem;
    font-size: 0.84rem;
    font-variant-numeric: tabular-nums;
    line-height: 1.45;
}

.gh-repo .details span {
    color: var(--color-muted);
    display: inline-block;
    margin-right: 0;
}

.gh-repo>div:first-child {
    display: flex;
    gap: 0.8rem;
    align-items: flex-start;
    justify-content: space-between;
}

.gh-repo .star-btn {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.4rem;
    padding: 0.38rem 0.7rem;
    color: var(--color-text);
    background: #f6f8fa;
    border: 1px solid #d0d7de;
    border-radius: 6px;
    box-shadow: 0 1px 0 rgba(27, 31, 36, 0.04);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.25rem;
    white-space: nowrap;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

.gh-repo .star-btn .icon {
    width: 0.9rem;
    height: 0.9rem;
    color: #57606a;
}

.gh-repo .star-btn:hover {
    color: var(--color-text);
    background: #eef1f4;
    border-color: #b8c0c8;
    box-shadow: 0 2px 5px rgba(27, 31, 36, 0.08);
}

.gh-repo .star-btn:active {
    background: #e7eaee;
    border-color: #afb8c1;
    box-shadow: inset 0 1px 2px rgba(27, 31, 36, 0.12);
    transform: translateY(1px);
}

.repos-error {
    color: var(--color-muted);
    text-align: center;
    margin: 1em;
}

.repos-loading {
    margin: 0 0 var(--space-block);
    padding: 0.75rem;
    color: var(--color-muted);
    text-align: center;
    background: var(--color-hover);
    border: 1px dashed var(--color-border);
    border-radius: 3px;
}

/* timeline */
#contests {
    --timeline-date-width: 5.5rem;
    --timeline-gap: 0.8rem;
}

.timeline {
    list-style: none;
    margin: 0.65rem 0 0;
    padding: 0;
}

.timeline-date {
    margin: 0;
    padding: 0.12rem 0.15rem 0 0;
    color: var(--color-muted);
    font-size: 0.78rem;
    font-style: italic;
    font-variant-numeric: tabular-nums;
    font-weight: 400;
    letter-spacing: 0.01em;
    line-height: 1.4;
    text-align: right;
}

.timeline>li {
    display: grid;
    grid-template-columns: var(--timeline-date-width) minmax(0, 1fr);
    gap: var(--timeline-gap);
    margin: 0;
}

.timeline>li[hidden] {
    display: none;
}

.timeline-content {
    position: relative;
    min-height: 2.9rem;
    padding: 0 0 0.8rem 1.1rem;
    border-left: 2px solid var(--color-accent-soft);
}

.timeline-content::before {
    content: "";
    position: absolute;
    top: 0.25rem;
    left: -5px;
    width: 8px;
    height: 8px;
    background: var(--color-accent);
    border: 2px solid var(--color-surface);
    border-radius: 50%;
    box-sizing: content-box;
}

.timeline>li:last-child .timeline-content,
.timeline>li.timeline-last-visible .timeline-content {
    border-left-color: transparent;
}

.timeline>li:last-child .timeline-content::after,
.timeline>li.timeline-last-visible .timeline-content::after {
    content: "";
    position: absolute;
    top: 0;
    left: -2px;
    height: 0.55rem;
    border-left: 2px solid var(--color-accent-soft);
}

.timeline-content>h3 {
    margin-block-start: 0;
    margin-block-end: 0;
    font-size: 1.05rem;
}

.timeline-content>p {
    margin-block-start: 0.08rem;
    margin-block-end: 0;
    color: var(--color-muted);
    font-size: 0.92rem;
    line-height: 1.4;
}

.timeline-toggle {
    display: inline-flex;
    min-height: 2rem;
    margin: 0 0 0 calc(var(--timeline-date-width) + var(--timeline-gap) + 1.1rem);
    padding: 0.25rem 0;
    align-items: center;
    gap: 0.45rem;
    color: var(--color-link);
    background: transparent;
    border: 0;
    font: 600 0.86rem/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    cursor: pointer;
    transition: color 150ms ease;
}

.timeline-toggle[hidden] {
    display: none;
}

.timeline-toggle:hover {
    color: var(--color-link-hover);
}

.timeline-toggle-chevron {
    width: 0.45rem;
    height: 0.45rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform 180ms ease;
}

.timeline-toggle[aria-expanded="true"] .timeline-toggle-chevron {
    transform: translateY(2px) rotate(225deg);
}

@media (max-width: 560px) {
    #contests {
        --timeline-date-width: 4.15rem;
        --timeline-gap: 0.55rem;
    }

    .event-list {
        --event-date-width: 4.15rem;
        --event-gap: 0.55rem;
    }

    .timeline-date {
        font-size: 0.72rem;
    }

    .event-date {
        font-size: 0.76rem;
    }

    .timeline-content {
        padding-left: 0.9rem;
    }

    .timeline-toggle {
        margin-left: calc(var(--timeline-date-width) + var(--timeline-gap) + 0.9rem);
    }

    .gh-repo>div:first-child {
        gap: 0.6rem;
    }

    .gh-repo .star-btn {
        padding-inline: 0.65rem;
    }
}

@media (max-width: 520px) {
    #job .event-list>li {
        grid-template-columns: minmax(0, 1fr);
        gap: 0.08rem;
    }

    #job .event-date {
        padding-top: 0;
        text-align: left;
    }
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        transition-duration: 0.01ms !important;
    }
}

@media print {
    @page {
        margin: 12mm;
    }

    body {
        background: #fff;
        font-size: 10pt;
    }

    .container {
        width: 100%;
        margin: 0;
        padding: 0;
        border: 0;
        box-shadow: none;
    }

    .avatar-container {
        top: 0;
        margin-bottom: 0;
    }

    .lang-switch,
    .section-nav,
    .timeline-toggle,
    .more,
    footer,
    .skip-link {
        display: none !important;
    }

    .timeline>li[hidden] {
        display: grid !important;
    }

    .timeline>li.timeline-last-visible .timeline-content {
        border-left-color: var(--color-accent-soft);
    }

    .timeline>li.timeline-last-visible .timeline-content::after {
        content: none;
    }

    .timeline>li:last-child .timeline-content {
        border-left-color: transparent;
    }

    .timeline>li:last-child .timeline-content::after {
        content: "";
    }

    .content,
    .gh-repo,
    .timeline>li {
        break-inside: avoid;
    }

    a {
        color: inherit;
    }
}
