Compare commits
No commits in common. "ab047959765e34a148ef136ad8bc33b8b0b14d22" and "043c5201d28c9e59a6af371b76314735a1a28338" have entirely different histories.
ab04795976
...
043c5201d2
4
content/.obsidian/app.json
vendored
|
@ -5,7 +5,5 @@
|
||||||
"vimMode": true,
|
"vimMode": true,
|
||||||
"useMarkdownLinks": false,
|
"useMarkdownLinks": false,
|
||||||
"attachmentFolderPath": "media",
|
"attachmentFolderPath": "media",
|
||||||
"alwaysUpdateLinks": true,
|
"alwaysUpdateLinks": true
|
||||||
"legacyEditor": false,
|
|
||||||
"promptDelete": false
|
|
||||||
}
|
}
|
34
content/.obsidian/workspace
vendored
|
@ -4,14 +4,13 @@
|
||||||
"type": "split",
|
"type": "split",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "23343431d6b81224",
|
"id": "642564a28e60933d",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "Spaceport.md",
|
"file": "Protospace.md",
|
||||||
"mode": "source",
|
"mode": "source"
|
||||||
"source": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +68,7 @@
|
||||||
"state": {
|
"state": {
|
||||||
"type": "backlink",
|
"type": "backlink",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "Spaceport.md",
|
"file": "Protospace.md",
|
||||||
"collapseAll": false,
|
"collapseAll": false,
|
||||||
"extraContext": false,
|
"extraContext": false,
|
||||||
"sortOrder": "alphabetical",
|
"sortOrder": "alphabetical",
|
||||||
|
@ -86,27 +85,28 @@
|
||||||
"state": {
|
"state": {
|
||||||
"type": "outline",
|
"type": "outline",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "Spaceport.md"
|
"file": "Protospace.md"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"currentTab": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "horizontal",
|
"direction": "horizontal",
|
||||||
"width": 300
|
"width": 300
|
||||||
},
|
},
|
||||||
"active": "23343431d6b81224",
|
"active": "642564a28e60933d",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"Spaceport.md",
|
|
||||||
"Backup Strategy.md",
|
|
||||||
"Protospace.md",
|
"Protospace.md",
|
||||||
"Notica.md",
|
"Plant Waterer.md",
|
||||||
"p.md",
|
"media/protospace2.png",
|
||||||
"QotNews.md",
|
"media/protospace1.png",
|
||||||
"media/Screenshot from 2022-05-18 16-24-38.png",
|
"Solar Car.md",
|
||||||
"media/Pasted image 20220518162452.png",
|
"Acousting Panels.md",
|
||||||
"media/Pasted image 20220518162414.png",
|
"Backup Strategy.md",
|
||||||
"Plant Waterer.md"
|
"Bypassing Ports.md",
|
||||||
|
"Garage Door Opener.md",
|
||||||
|
"Painting.md"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
Title: Notica
|
|
||||||
Date: 2022-05-17
|
|
||||||
Category: Projects
|
|
||||||
Summary: Send browser notifications from your terminal. No installation. No registration.
|
|
||||||
Short: n
|
|
||||||
|
|
||||||
[Notica](https://notica.us) allows you to send browser notifications from your terminal to know when a slow command has finished running. It doesn't require installing anything or registering an account. It also works over ssh unlike `notify-send`.
|
|
||||||
|
|
||||||
You can find the [source code](https://github.com/tannercollin/Notica) on Github.
|
|
||||||
|
|
||||||
![[notica1.png]]
|
|
||||||
|
|
||||||
I do most of my work on remote servers over ssh. When running a slow command (like `apt install`) I'll distract myself by browsing sites like my other project [[QotNews]]. The command will finish running, but I'll still be wasting time reading news articles. Notica helps me stay on track by alerting me when the command finishes.
|
|
|
@ -1,55 +0,0 @@
|
||||||
Title: Protospace
|
|
||||||
Date: 2022-05-01
|
|
||||||
Category: Writing
|
|
||||||
Summary: An outline of my projects at Calgary's makerspace Protospace.
|
|
||||||
Wide: true
|
|
||||||
Short: protospace
|
|
||||||
|
|
||||||
[Protospace](https://protospace.ca) is Calgary's original makerspace, a place where people go to make things and work on projects. It's a two-bay industrial shop with a full wood working area, metal working area, electronics lab, two laser cutters, five 3D printers, and sewing room. Members pay $55/month for 24/7 access to the facility and everyone is equal: Protospace has no owners and decisions are made by the membership.
|
|
||||||
|
|
||||||
![[protospace1.jpg | both Protospace bays, metal on the left and wood on the right]]
|
|
||||||
|
|
||||||
## Do-ocracy
|
|
||||||
|
|
||||||
The driving principle behind Protospace's success is do-ocracy. If you want to make a change and it would take fewer than four hours to revert, go ahead and do it. Under a do-ocracy people are encouraged to be bold and improve the space however they want. Larger changes and disagreements are decided at the next monthly members' meeting.
|
|
||||||
|
|
||||||
Under this system, I've created several projects in order to make Protospace a better place. I'll outline them here:
|
|
||||||
|
|
||||||
### Spaceport
|
|
||||||
|
|
||||||
[[Spaceport]] is our member portal and my main project at Protospace. It tracks memberships, transactions, courses, class attendance, access cards, and statistics about Protospace and its members.
|
|
||||||
|
|
||||||
It's free and open-source software. Everyone has the right to study, change, and distribute the software and source code to anyone and for any purpose. Here's a screenshot of the home page:
|
|
||||||
|
|
||||||
![[spaceport1.png | a screenshot of the homepage of Spaceport]]
|
|
||||||
|
|
||||||
### Garden
|
|
||||||
|
|
||||||
I set up a simple hydroponics garden in a broken medical lung testing chamber that someone donated to us. Some members have a hard time turning down free junk, and it sat upstairs for about a month in the classroom filled with lung testing equipment. I eventually got tired of looking at it so one night I gutted it and threw out all the internals.
|
|
||||||
|
|
||||||
A picture of the garden is taken every 5 minutes and uploaded to Spaceport. I'll eventually make a time lapse of the vegetable growth and plot a graph of the internal air temperature.
|
|
||||||
|
|
||||||
![[protospace-garden.png]]
|
|
||||||
|
|
||||||
### Telemetry
|
|
||||||
|
|
||||||
Telemetry is a catch-all project for random sensors and displays around Protospace.
|
|
||||||
|
|
||||||
- Two air quality and temperature sensors
|
|
||||||
- A web server for querying sensor data
|
|
||||||
- Alarm armed / disarmed sensor
|
|
||||||
- A script that detects who's logged into various computers
|
|
||||||
|
|
||||||
Here's a graph of the air quality on Spaceport:
|
|
||||||
|
|
||||||
![[protospace-dust.png]]
|
|
||||||
|
|
||||||
### Airlock
|
|
||||||
|
|
||||||
Airlock is our door lock controller. Vetted Protospace members are given key cards which they scan to access the building 24/7. Airlock periodically polls a list of valid card numbers from Spaceport and checks scans against that list. If a valid card number is scanned, a relay and electric latch is opened. The card number is also reported back to Spaceport so that it can keep a log of who scanned when.
|
|
||||||
|
|
||||||
### Doorbell
|
|
||||||
|
|
||||||
We have a doorbell because members who aren't yet vetted don't get a key card and can't scan into the building 24/7. Instead they have to use the doorbell to request entry into the building. Our normal wireless doorbell's chime isn't loud enough to hear throughout the space and you can't tell which door the person is at (front or back).
|
|
||||||
|
|
||||||
I used a software-defined radio to detect our wireless doorbell's signal and play a chime over the PA system throughout the entire space. A voice then says whether it was triggered by the front door or back door.
|
|
|
@ -1,17 +0,0 @@
|
||||||
Title: QotNews
|
|
||||||
Date: 2022-05-18
|
|
||||||
Category: Projects
|
|
||||||
Summary: Hacker News, Reddit, Lobsters, and Tildes articles pre-rendered in reader mode. Optimized for speed and distraction-free reading.
|
|
||||||
Short: q
|
|
||||||
|
|
||||||
[QotNews](https://news.t0.vc) is a news meta-aggregator. It gathers top articles from four news aggregators: Hacker News, Reddit, Lobsters, and Tildes along with their comments. The articles are then transformed into readable versions with consistent formatting and distractions removed. All articles in the main feed are preloaded by the client so they load instantly when clicked on.
|
|
||||||
|
|
||||||
You can find the [source code](https://git.tannercollin.com/tanner/qotnews) on my Gitea.
|
|
||||||
|
|
||||||
![[qotnews1.png]]
|
|
||||||
|
|
||||||
I tried to make QotNews the perfect news site for me. I easily get annoyed by cookie banners and distracted by visual clutter when reading normal news articles. I especially hate auto-playing videos and "download our app" popups. All articles are in consistent styling that's easy to read:
|
|
||||||
|
|
||||||
![[qotnews2.png]]
|
|
||||||
|
|
||||||
It's by far my favourite project and has paid the most dividends for the amount of time I invested in programming it. I use it multiple times per day and it's become the main source of all my news. Since all the articles and comments are preloaded and saved in Local Storage, it's also great for reading on airplanes.
|
|
|
@ -1,35 +0,0 @@
|
||||||
Title: Spaceport
|
|
||||||
Date: 2022-05-16
|
|
||||||
Category: Projects
|
|
||||||
Summary: Member portal for Calgary Protospace. It tracks dues, courses, training, access cards, and more.
|
|
||||||
Short: m
|
|
||||||
|
|
||||||
[Spaceport](https://my.protospace.ca) is the member portal that I wrote for [[Protospace]], a makerspace that I frequent in Calgary. It is by far my largest project and the one I've spent the most time on. It has a database of all our members and tracks their transactions like dues and training fees. It allows members to sign up for classes and our instructors to teach courses. It also manages the access cards that members use to get into the building.
|
|
||||||
|
|
||||||
You can find the [source code](https://github.com/Protospace/spaceport) on Github.
|
|
||||||
|
|
||||||
![[spaceport1.png]]
|
|
||||||
|
|
||||||
Spaceport is tightly coupled to Protospace and has many integrations:
|
|
||||||
|
|
||||||
- Syncs credentials to our AD controller for computer logins
|
|
||||||
- Manages AD group membership to restrict machine use
|
|
||||||
- Syncs credentials to our Discourse forum [Spacebar](https://forum.protospace.ca)
|
|
||||||
- Manages Discourse groups to restrict topic access
|
|
||||||
- Syncs credentials to our [MediaWiki](https://wiki.protospace.ca)
|
|
||||||
- Processes PayPal payment notifications
|
|
||||||
- Syncs valid member cards to our door controller Airlock
|
|
||||||
- Tracks training certifications for our tool lockouts
|
|
||||||
- Emails interested members when a class is scheduled
|
|
||||||
- Shows who's connected to our [Minecraft server](http://games.protospace.ca:8123/?worldname=world&mapname=flat&zoom=3&x=74&y=64&z=354)
|
|
||||||
- Tracks who's logged into our laser cutter and CNC router
|
|
||||||
- Tracks and bills for laser cutting time
|
|
||||||
- Shows if the building alarm is armed or disarmed
|
|
||||||
- Displays charts of various environmental sensors
|
|
||||||
- Displays a photo of our garden
|
|
||||||
|
|
||||||
![[spaceport2.png]]
|
|
||||||
|
|
||||||
As of writing this there's 234 current Protospace members and 1408 historical or inactive memberships that it manages. Data is stored in a 49 MB SQLite database which makes it easy to back up or sync with my development server. The back end is written in Django / Python and the front end is React / JavaScript with Semantic UI for the graphics.
|
|
||||||
|
|
||||||
Site data is automatically compressed and [[Backup Strategy | backed up]] daily by two members. The software is free and open-source and can be set up by reading the documentation. Protospace directors also have admin access to the server's host in case something happens to me.
|
|
Before Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 577 KiB |
Before Width: | Height: | Size: 212 KiB |
Before Width: | Height: | Size: 182 KiB |
Before Width: | Height: | Size: 211 KiB |
Before Width: | Height: | Size: 152 KiB |
|
@ -36,7 +36,6 @@ MARKDOWN = {
|
||||||
|
|
||||||
PLUGINS = [
|
PLUGINS = [
|
||||||
'obsidian',
|
'obsidian',
|
||||||
'linkclass',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
STATIC_PATHS = ['media', 'extra']
|
STATIC_PATHS = ['media', 'extra']
|
||||||
|
|
|
@ -34,12 +34,7 @@ MARKDOWN = {
|
||||||
'output_format': 'html5',
|
'output_format': 'html5',
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGINS = [
|
STATIC_PATHS = ['images', 'extra']
|
||||||
'obsidian',
|
|
||||||
'linkclass',
|
|
||||||
]
|
|
||||||
|
|
||||||
STATIC_PATHS = ['media', 'extra']
|
|
||||||
|
|
||||||
EXTRA_PATH_METADATA = {
|
EXTRA_PATH_METADATA = {
|
||||||
'extra/favicon.svg': {'path': 'favicon.svg'},
|
'extra/favicon.svg': {'path': 'favicon.svg'},
|
||||||
|
|
|
@ -6,7 +6,6 @@ Jinja2==3.1.2
|
||||||
Markdown==3.3.6
|
Markdown==3.3.6
|
||||||
MarkupSafe==2.1.1
|
MarkupSafe==2.1.1
|
||||||
pelican==4.7.2
|
pelican==4.7.2
|
||||||
pelican-linkclass==2.0.2
|
|
||||||
pelican-obsidian @ git+https://git.tannercollin.com/tanner/pelican-obsidian.git@41dd1d649127ae2833f5a4b1c3b6b6cb571117d8
|
pelican-obsidian @ git+https://git.tannercollin.com/tanner/pelican-obsidian.git@41dd1d649127ae2833f5a4b1c3b6b6cb571117d8
|
||||||
Pygments==2.12.0
|
Pygments==2.12.0
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block info %}
|
{% block info %}
|
||||||
<p>← <a class="return-home" href="/">Return Home</a></p>
|
<p>← <a href="/">Return Home</a></p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -53,6 +53,4 @@
|
||||||
{{ article.content }}
|
{{ article.content }}
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>← <a class="return-home" href="/">Return Home</a></p>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -40,10 +40,10 @@
|
||||||
<h2>Resume</h2>
|
<h2>Resume</h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Firmware Engineer at <a class="external" href="https://cabanablockchain.com" target="_blank" rel="noreferrer noopener">Cabana Blockchain</a>, 2018–</li>
|
<li>Firmware Engineer at <a href="https://cabanablockchain.com" target="_blank" rel="noreferrer noopener">Cabana Blockchain</a>, 2018–</li>
|
||||||
<li>Lead Hardware Engineer at <a class="external" href="https://criticalcontrol.com/" target="_blank" rel="noreferrer noopener">Critical Control</a>, 2016–2018</li>
|
<li>Lead Hardware Engineer at <a href="https://criticalcontrol.com/" target="_blank" rel="noreferrer noopener">Critical Control</a>, 2016–2018</li>
|
||||||
<li>Electrical Engineer at <a class="external" href="https://www.opener.aero/" target="_blank" rel="noreferrer noopener">Opener Aero</a>, 2016–2016</li>
|
<li>Electrical Engineer at <a href="https://www.opener.aero/" target="_blank" rel="noreferrer noopener">Opener Aero</a>, 2016–2016</li>
|
||||||
<li>Electrical Engineer Intern at <a class="external" href="https://www.pason.com/" target="_blank" rel="noreferrer noopener">Pason Systems</a>, 2014–2015</li>
|
<li>Electrical Engineer Intern at <a href="https://www.pason.com/" target="_blank" rel="noreferrer noopener">Pason Systems</a>, 2014–2015</li>
|
||||||
<li>BSc. Electrical Engineering from University of Calgary</li>
|
<li>BSc. Electrical Engineering from University of Calgary</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -54,23 +54,40 @@
|
||||||
build tools that make my life easier.
|
build tools that make my life easier.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% for article in articles_page.object_list if article.category.name == 'Projects' %}
|
<h3>
|
||||||
<h3><a href="{{ article.url }}">{{ article.title }}</a></h3>
|
<a href="https://news.t0.vc/" target="_blank" rel="noreferrer noopener">QotNews</a>
|
||||||
<div class="summary">
|
— <a class="source" href="https://git.tannercollin.com/tanner/qotnews" target="_blank" rel="noreferrer noopener">source code</a>
|
||||||
{{ article.summary }}
|
</h3>
|
||||||
</div>
|
<div class="summary">
|
||||||
{% endfor %}
|
<p>Hacker News, Reddit, Lobsters, and Tildes articles pre-rendered in reader mode. Optimized for speed and distraction-free reading.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
<a class="external" href="https://txt.t0.vc" target="_blank" rel="noreferrer noopener">t0txt</a>
|
<a href="https://notica.us" target="_blank" rel="noreferrer noopener">Notica</a>
|
||||||
— <a class="external source" href="https://github.com/tannercollin/t0txt" target="_blank" rel="noreferrer noopener">source code</a>
|
— <a class="source" href="https://github.com/tannercollin/Notica" target="_blank" rel="noreferrer noopener">source code</a>
|
||||||
|
</h3>
|
||||||
|
<div class="summary">
|
||||||
|
<p>Send browser notifications from your terminal. No installation. No registration.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="https://my.protospace.ca" target="_blank" rel="noreferrer noopener">Spaceport</a>
|
||||||
|
— <a class="source" href="https://github.com/Protospace/spaceport" target="_blank" rel="noreferrer noopener">source code</a>
|
||||||
|
</h3>
|
||||||
|
<div class="summary">
|
||||||
|
<p>Makerspace members' portal for Calgary Protospace. It tracks membership, courses, training, access cards, and more.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a href="https://txt.t0.vc" target="_blank" rel="noreferrer noopener">t0txt</a>
|
||||||
|
— <a class="source" href="https://github.com/tannercollin/t0txt" target="_blank" rel="noreferrer noopener">source code</a>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
<p>Minimal command line pastebin. Allows you to upload text notes from a bash pipe or web browser.</p>
|
<p>Minimal command line pastebin. Allows you to upload text notes from a bash pipe or web browser.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
<a class="external" href="https://github.com/tannercollin/standardnotes-fs" target="_blank" rel="noreferrer noopener">standardnotes-fs</a>
|
<a href="https://github.com/tannercollin/standardnotes-fs" target="_blank" rel="noreferrer noopener">standardnotes-fs</a>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="summary">
|
<div class="summary">
|
||||||
<p>A filesystem that mounts your Standard Notes account as a directory of text files that you can edit.</p>
|
<p>A filesystem that mounts your Standard Notes account as a directory of text files that you can edit.</p>
|
||||||
|
|
|
@ -12,13 +12,6 @@ a {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.external {
|
|
||||||
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath fill='%23fff' stroke='%23000' d='M1.5 4.518h5.982V10.5H1.5z'/%3E%3Cpath fill='%23000' d='M5.765 1H11v5.39L9.427 7.937l-1.31-1.31L5.393 9.35l-2.69-2.688 2.81-2.808L4.2 2.544z'/%3E%3Cpath fill='%23fff' d='m9.995 2.004.022 4.885L8.2 5.07 5.32 7.95 4.09 6.723l2.882-2.88-1.85-1.852z'/%3E%3C/svg%3E%0A");
|
|
||||||
background-position: center right;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info h1 {
|
.info h1 {
|
||||||
font: 1.1rem/1.0 sans-serif;
|
font: 1.1rem/1.0 sans-serif;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +68,7 @@ pre {
|
||||||
}
|
}
|
||||||
|
|
||||||
.content div.summary p {
|
.content div.summary p {
|
||||||
margin-top: -0.6rem;
|
margin-top: -0.5rem;
|
||||||
margin-left: 1.5rem;
|
margin-left: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +94,6 @@ pre {
|
||||||
|
|
||||||
.content img {
|
.content img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 36rem;
|
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +180,7 @@ pre {
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: #fff;
|
background-color: #eee;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,16 +189,6 @@ a {
|
||||||
border-bottom: 1px solid #000;
|
border-bottom: 1px solid #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: #555;
|
|
||||||
border-bottom: 1px solid #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.return-home:visited, a.toclink:visited, .toc a:visited {
|
|
||||||
color: inherit;
|
|
||||||
border-bottom: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background-color: #ddd;
|
background-color: #ddd;
|
||||||
}
|
}
|
||||||
|
@ -226,17 +208,12 @@ pre {
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
body {
|
body {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
color: #fff;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #fff;
|
color: #eee;
|
||||||
border-bottom: 1px solid #fff;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
|
||||||
|
|
||||||
a:visited {
|
|
||||||
color: #aaa;
|
|
||||||
border-bottom: 1px solid #aaa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
|
|